Links
setup.cfg filespyproject.toml filespkg_resourcesProject
setup() Keywordsdependency_linkszip_safe flagsetuptools commandsYou can install the latest version ofsetuptools usingpip:
pipinstall--upgradesetuptools[core]
Most of the times, however, you don’t have to…
Instead, when creating new Python packages, it is recommended to usea command line tool calledbuild. This tool will automatically downloadsetuptools and any other build-time dependencies that your project mighthave. You just need to specify them in apyproject.toml file at the root ofyour package, as indicated in thefollowing section.
You can alsoinstall build usingpip:
pipinstall--upgradebuild
This will allow you to run the command:python-mbuild.
Important
Please note that some operating systems might be equipped withthepython3 andpip3 commands instead ofpython andpip(but they should be equivalent).If you don’t havepip orpip3 available in your system, pleasecheck outpip installation docs.
Every python package must provide apyproject.toml and specifythe backend (build system) it wants to use. The distribution can thenbe generated with whatever tool that provides abuildsdist-likefunctionality.
When creating a Python package, you must provide apyproject.toml filecontaining abuild-system section similar to the example below:
[build-system]requires=["setuptools"]build-backend="setuptools.build_meta"
This section declares what are your build system dependencies, and whichlibrary will be used to actually do the packaging.
Note
Package maintainers might be tempted to usesetuptools[core] as therequirement, given the guidance above. Avoid doing so, as the extrais currently considered an internal implementation detail and is likelyto go away in the future and the Setuptools team will not supportcompatibility for problems arising from packages published with thisextra declared. Vendored packages will satisfy the dependencies inthe most common isolated build scenarios.
Note
Historically this documentation has unnecessarily listedwheelin therequires list, and many projects still do that. This isnot recommended, as the backend no longer requires thewheelpackage, and listing it explicitly causes it to be unnecessarilyrequired for source distribution builds.You should only includewheel inrequires if you need to explicitlyaccess it during build time (e.g. if your project needs asetup.pyscript that importswheel).
In addition to specifying a build system, you also will need to addsome package information such as metadata, contents, dependencies, etc.This can be done in the samepyproject.toml file,or in a separated one:setup.cfg orsetup.py[1].
The following example demonstrates a minimum configuration(which assumes the project depends onrequests andimportlib-metadata to be able to run):
[project]name="mypackage"version="0.0.1"dependencies=["requests",'importlib-metadata; python_version<"3.10"',]
SeeConfiguring setuptools using pyproject.toml files for more information.
[metadata]name=mypackageversion=0.0.1[options]install_requires=requestsimportlib-metadata; python_version<"3.10"
SeeConfiguring setuptools using setup.cfg files for more information.
fromsetuptoolsimportsetupsetup(name='mypackage',version='0.0.1',install_requires=['requests','importlib-metadata; python_version<"3.10"',],)
SeeKeywords for more information.
Finally, you will need to organize your Python code to make it ready fordistributing into something that looks like the following(optional files marked with#):
mypackage├── pyproject.toml # and/or setup.cfg/setup.py (depending on the configuration method)| # README.rst or README.md (a nice description of your package)| # LICENCE (properly chosen license information, e.g. MIT, BSD-3, GPL-3, MPL-2, etc...)└── mypackage ├── __init__.py └── ... (other Python files)
Withbuild installed in your system, you can then run:
python-mbuild
You now have your distribution ready (e.g. atar.gz file and a.whl filein thedist directory), which you canupload toPyPI!
Of course, before you release your project toPyPI, you’ll want to add a bitmore information to help people find or learn about your project.And maybe your project will have grown by then to include a fewdependencies, and perhaps some data files and scripts. In the next few sections,we will walk through the additional but essential information you needto specify to properly package your project.
Info: Usingsetup.py
Setuptools offers first class support forsetup.py files as a configurationmechanism.
It is important to remember, however, that running this file as ascript (e.g.pythonsetup.pysdist) is stronglydiscouraged, andthat the majority of the command line interfaces are (or will be)deprecated(e.g.pythonsetup.pyinstall,pythonsetup.pybdist_wininst, …).
We also recommend users to expose as much as possible configuration in amoredeclarative way via thepyproject.toml orsetup.cfg, and keep thesetup.py minimalwith only the dynamic parts (or even omit it completely if applicable).
SeeWhy you shouldn’t invoke setup.py directly for more background.
For projects that follow a simple directory structure,setuptools should beable to automatically detect allpackages andnamespaces. However, complex projects might includeadditional folders and supporting files that not necessarily should bedistributed (or that can confusesetuptools auto discovery algorithm).
Therefore,setuptools provides a convenient way to customizewhich packages should be distributed and in which directory they should befound, as shown in the example below:
# ...[tool.setuptools.packages]find={}# Scan the project directory with the default parameters# OR[tool.setuptools.packages.find]# All the following settings are optional:where=["src"]# ["."] by defaultinclude=["mypackage*"]# ["*"] by defaultexclude=["mypackage.tests*"]# empty by defaultnamespaces=false# true by default
[options]packages=find:# OR `find_namespace:` if you want to use namespaces[options.packages.find] # (always `find` even if `find_namespace:` was used before)# This section is optional as well as each of the following options:where=src# . by defaultinclude=mypackage*# * by defaultexclude=mypackage.tests*# empty by default
fromsetuptoolsimportsetup,find_packages# or find_namespace_packagessetup(# ...packages=find_packages(# All keyword arguments below are optional:where='src',# '.' by defaultinclude=['mypackage*'],# ['*'] by defaultexclude=['mypackage.tests'],# empty by default),# ...)
When you pass the above information, alongside other necessary information,setuptools walks through the directory specified inwhere (defaults to.) and filters the packagesit can find following theinclude patterns (defaults to*), then it removesthose that match theexclude patterns (defaults to empty) and returns a list of Python packages.
For more details and advanced use, go toPackage Discovery and Namespace Packages.
Tip
Starting with version 61.0.0, setuptools’ automatic discovery capabilitieshave been improved to detect popular project layouts (such as theflat-layout andsrc-layout) without requiring anyspecial configuration. Check out ourreference docsfor more information.
Setuptools supports automatic creation of scripts upon installation, that runcode within your package if you specify them asentry points.An example of how this feature can be used inpip:it allows you to run commands likepipinstall instead of havingto typepython-mpipinstall.
The following configuration examples show how to accomplish this:
[project.scripts]cli-name="mypkg.mymodule:some_func"
[options.entry_points]console_scripts=cli-name=mypkg.mymodule:some_func
setup(# ...entry_points={'console_scripts':['cli-name = mypkg.mymodule:some_func',]})
When this project is installed, acli-name executable will be created.cli-name will invoke the functionsome_func in themypkg/mymodule.py file when called by the user.Note that you can also use theentry-points mechanism to advertisecomponents between installed packages and implement plugin systems.For detailed usage, go toEntry Points.
Packages built withsetuptools can specify dependencies to be automaticallyinstalled when the package itself is installed.The example below shows how to configure this kind of dependencies:
[project]# ...dependencies=["docutils","requests <= 0.4",]# ...
[options]install_requires=docutilsrequests <=0.4
setup(# ...install_requires=["docutils","requests <= 0.4"],# ...)
Each dependency is represented by a string that can optionally contain version requirements(e.g. one of the operators <, >, <=, >=, == or !=, followed by a version identifier),and/or conditional environment markers, e.g.sys_platform=="win32"(seeVersion specifiers for more information).
When your project is installed, all of the dependencies not already installedwill be located (via PyPI), downloaded, built (if necessary), and installed.This, of course, is a simplified scenario. You can also specify groups ofextra dependencies that are not strictly required by your package to work, butthat will provide additional functionalities.For more advanced use, seeDependencies Management in Setuptools.
Setuptools offers three ways to specify data files to be included in your packages.For the simplest use, you can simply use theinclude_package_data keyword:
[tool.setuptools]include-package-data=true# This is already the default behaviour if you are using# pyproject.toml to configure your build.# You can deactivate that with `include-package-data = false`
[options]include_package_data=True
setup(# ...include_package_data=True,# ...)
This tells setuptools to install any data files it finds in your packages.The data files must be specified via theMANIFEST.infile or automatically added by aRevision Control System plugin.For more details, seeData Files Support.
setuptools allows you to install a package without copying any filesto your interpreter directory (e.g. thesite-packages directory).This allows you to modify your source code and have the changes takeeffect without you having to rebuild and reinstall.Here’s how to do it:
pipinstall--editable.
SeeDevelopment Mode (a.k.a. “Editable Installs”) for more information.
Tip
Prior topip v21.1, asetup.py script wasrequired to be compatible with development mode. With lateversions of pip, projects withoutsetup.py may be installed in this mode.
If you have a version ofpip older than v21.1 or is using a differentpackaging-related tool that does not supportPEP 660, you might need to keep asetup.py file in your repository if you want to use editableinstalls.
A simple script will suffice, for example:
fromsetuptoolsimportsetupsetup()
You can still keep all the configuration inpyproject.toml and/orsetup.cfg
Note
When building from source code (for example, bypython-mbuildorpipinstall-e.)some directories hosting build artefacts and cache files may becreated, such asbuild,dist,*.egg-info[2].You can configure your version control system to ignore them(seeGitHub’s .gitignore templatefor an example).
After generating the distribution files, the next step would be to upload yourdistribution so others can use it. This functionality is provided bytwine and is documented in thePython packaging tutorial.
setup.py to declarative config¶To avoid executing arbitrary scripts and boilerplate code, we are transitioningfrom defining all your package information by runningsetup() to doing thisdeclaratively - by usingpyproject.toml (or oldersetup.cfg).
To ease the challenges of transitioning, we provide a quickguide to understanding howpyproject.tomlis parsed bysetuptools. (Alternatively, here is theguide forsetup.cfg).
Note
The approachsetuptools would like to take is to eventually use a singledeclarative format (pyproject.toml) instead of maintaining 2(pyproject.toml /setup.cfg). Yet, chances are,setup.cfg willcontinue to be maintained for a long time.
Packaging in Python can be hard and is constantly evolving.Python Packaging User Guide has tutorials andup-to-date references that can help you when it is time to distribute your work.
Notes
[1](1,2,3,4,5,6)New projects are advised to avoidsetup.py configurations (beyond the minimal stub)when custom scripting during the build is not necessary.Examples are kept in this document to help people interested in maintaining orcontributing to existing packages that usesetup.py.Note that you can still keep most of configuration declarative insetup.cfg orpyproject.toml and usesetup.py only for the parts notsupported in those files (e.g. C extensions).Seenote.
If you feel that caching is causing problems to your build, specially after changes in theconfiguration files, consider removingbuild,dist,*.egg-info beforerebuilding or installing your project.