To install the latest version of setuptools, use:
pip install --upgrade setuptools
The landscape of Python packaging is shifting and Setuptools
has evolved to only provide backend support, no longer being the de-facto packaging tool in the market. Every python package must provide a pyproject.toml
and specify the backend (build system) it wants to use. The distribution can then be generated with whatever tool that provides a build sdist
-like functionality. While this may appear cumbersome, given the added pieces, it in fact tremendously enhances the portability of your package. The change is driven under PEP 517 <517#build-requirements>
. To learn more about Python packaging in general, navigate to the bottom <packaging-resources>
of this page.
For basic use of setuptools, you will need a pyproject.toml
with the exact following info, which declares you want to use setuptools
to package your project:
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
Then, you will need to specify your package information such as metadata, contents, dependencies, etc.
Setuptools currently supports configurations from either setup.cfg
, setup.py
or pyproject.toml
1 files, however, configuring new projects via setup.py
is discouraged2.
The following example demonstrates a minimum configuration:
setup.cfg
[metadata]
name = mypackage
version = 0.0.1
[options]
packages = mypackage
install_requires =
requests
importlib-metadata; python_version < "3.8"
See /userguide/declarative_config
for more information.
setup.py3
from setuptools import setup
setup(
name='mypackage',
version='0.0.1',
packages=['mypackage'],
install_requires=[
'requests',
'importlib-metadata; python_version == "3.8"',
],
)
See /references/keywords
for more information.
pyproject.toml (EXPERIMENTAL)4
[project]
name = "mypackage"
version = "0.0.1"
dependencies = [
"requests",
'importlib-metadata; python_version<"3.8"',
]
See /userguide/pyproject_config
for more information.
This is what your project would look like:
~/mypackage/
pyproject.toml
setup.cfg # or setup.py
mypackage/__init__.py
Then, you need a builder, such as :stdPyPA build <pypa-build:index>
which you can obtain via pip install build
. After downloading it, invoke the builder:
python -m build
You now have your distribution ready (e.g. a tar.gz
file and a .whl
file in the dist
directory), which you can upload to PyPI!
Of course, before you release your project to PyPI, you'll want to add a bit more information to your setup script to help people find or learn about your project. And maybe your project will have grown by then to include a few dependencies, and perhaps some data files and scripts. In the next few sections, we will walk through the additional but essential information you need to specify to properly package your project.
For simple projects, it's usually easy enough to manually add packages to the packages
keyword in setup.cfg
. However, for very large projects, it can be a big burden to keep the package list updated. Therefore, setuptools
provides a convenient way to automatically list all the packages in your project directory:
setup.cfg
[options]
packages = find: # OR `find_namespaces:` if you want to use namespaces
[options.packages.find] # (always `find` even if `find_namespaces:` was used before)
# This section is optional
# Each entry in this section is optional, and if not specified, the default values are:
# `where=.`, `include=*` and `exclude=` (empty).
include=mypackage*
exclude=mypackage.tests*
setup.py5
from setuptools import find_packages # or find_namespace_packages
setup(
# ...
packages=find_packages(
where='.',
include=['mypackage*'], # ["*"] by default
exclude=['mypackage.tests'], # empty by default
),
# ...
)
pyproject.toml (EXPERIMENTAL)6
# ...
[tool.setuptools.packages]
find = {} # Scan the project directory with the default parameters
# OR
[tool.setuptools.packages.find]
where = ["src"] # ["."] by default
include = ["mypackage*"] # ["*"] by default
exclude = ["mypackage.tests*"] # empty by default
namespaces = false # true by default
When you pass the above information, alongside other necessary information, setuptools
walks through the directory specified in where
(omitted here as the package resides in the current directory) and filters the packages it can find following the include
(defaults to none), then removes those that match the exclude
and returns a list of Python packages. The above setup also allows you to adopt a src/
layout. For more details and advanced use, go to package_discovery
.
Tip
Starting with version 61.0.0, setuptools' automatic discovery capabilities have been improved to detect popular project layouts (such as the flat-layout
and src-layout
) without requiring any special configuration. Check out our reference docs <package_discovery>
for more information, but please keep in mind that this functionality is still considered experimental and might change (or even be removed) in future releases.
Setuptools supports automatic creation of scripts upon installation, that runs code within your package if you specify them as entry points
<PyPUG:specifications/entry-points>
. This is what allows you to run commands like pip install
instead of having to type python -m pip install
. The following configuration examples show how to accomplish this:
setup.cfg
[options.entry_points]
console_scripts =
cli-name = mypkg.mymodule:some_func
setup.py7
setup(
# ...
entry_points={
'console_scripts': [
'cli-name = mypkg.mymodule:some_func',
]
}
)
pyproject.toml (EXPERIMENTAL)8
[project.scripts]
cli-name = "mypkg.mymodule:some_func"
When this project is installed, a cli-name
executable will be created. cli-name
will invoke the function some_func
in the mypkg/mymodule.py
file when called by the user. Note that you can also use the entry-points
mechanism to advertise components between installed packages and implement plugin systems. For detailed usage, go to entry_point
.
Packages built with setuptools
can specify dependencies to be automatically installed when the package itself is installed. The example below show how to configure this kind of dependencies:
setup.cfg
[options]
install_requires =
docutils
requests <= 0.4
setup.py9
setup(
# ...
install_requires=["docutils", "requests <= 0.4"],
# ...
)
pyproject.toml (EXPERIMENTAL)10
[project]
# ...
dependencies = [
"docutils",
"requires <= 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"
(see PyPUG:specifications/version-specifiers
for more information).
When your project is installed, all of the dependencies not already installed will be located (via PyPI), downloaded, built (if necessary), and installed. This, of course, is a simplified scenario. You can also specify groups of extra dependencies that are not strictly required by your package to work, but that will provide additional functionalities. For more advanced use, see dependency_management
.
The distutils have traditionally allowed installation of "data files", which are placed in a platform-specific location. Setuptools offers three ways to specify data files to be included in your packages. For the simplest use, you can simply use the include_package_data
keyword:
setup.cfg
[options]
include_package_data = True
setup.py11
setup(
# ...
include_package_data=True,
# ...
)
pyproject.toml (EXPERIMENTAL)12
[tool.setuptools]
include-package-data = true
# This is already the default behaviour if your are using
# pyproject.toml to configure your build.
# You can deactivate that with `include-package-data = false`
This tells setuptools to install any data files it finds in your packages. The data files must be specified via the distutils' MANIFEST.in
_ file or automatically added by a Revision Control System plugin
<Adding Support for Revision Control Systems>
. For more details, see datafiles
.
setuptools
allows you to install a package without copying any files to your interpreter directory (e.g. the site-packages
directory). This allows you to modify your source code and have the changes take effect without you having to rebuild and reinstall. Here's how to do it:
pip install --editable .
This creates a link file in your interpreter site package directory which associate with your source code. For more information, see development_mode
.
Tip
Prior to pip v21.1 <pip:v21-1>
, a setup.py
script was required to be compatible with development mode. With late versions of pip, setup.cfg
-only projects may be installed in this mode.
If you are experimenting with configuration using <pyproject_config>
, or have version of pip
older than v21.1, you might need to keep a setup.py
file in file in your repository if you want to use editable installs (for the time being).
A simple script will suffice, for example:
from setuptools import setup
setup()
You can still keep all the configuration in setup.cfg </userguide/declarative_config>
(or pyproject.toml </userguide/pyproject_config>
).
After generating the distribution files, the next step would be to upload your distribution so others can use it. This functionality is provided by twine
and is documented in the Python packaging tutorial
<PyPUG:tutorials/packaging-projects>
.
To avoid executing arbitrary scripts and boilerplate code, we are transitioning into a full-fledged setup.cfg
to declare your package information instead of running setup()
. This inevitably brings challenges due to a different syntax. Here </userguide/declarative_config>
we provide a quick guide to understanding how setup.cfg
is parsed by setuptools
to ease the pain of transition.
Packaging in Python can be hard and is constantly evolving. Python Packaging User Guide has tutorials and up-to-date references that can help you when it is time to distribute your work.
Notes
While the
[build-system]
table should always be specified in thepyproject.toml
file, support for adding package metadata and build configuration options via the[project]
and[tool.setuptools]
tables is still experimental and might change (or be completely removed) in future releases. See/userguide/pyproject_config
.↩The
setup.py
file should be used only when custom scripting during the build is necessary. Examples are kept in this document to help people interested in maintaining or contributing to existing packages that usesetup.py
. Note that you can still keep most of configuration declarative insetup.cfg <declarative_config>
orpyproject.toml <pyproject_config>
and usesetup.py
only for the parts not supported in those files (e.g. C extensions).↩The
setup.py
file should be used only when custom scripting during the build is necessary. Examples are kept in this document to help people interested in maintaining or contributing to existing packages that usesetup.py
. Note that you can still keep most of configuration declarative insetup.cfg <declarative_config>
orpyproject.toml <pyproject_config>
and usesetup.py
only for the parts not supported in those files (e.g. C extensions).↩While the
[build-system]
table should always be specified in thepyproject.toml
file, support for adding package metadata and build configuration options via the[project]
and[tool.setuptools]
tables is still experimental and might change (or be completely removed) in future releases. See/userguide/pyproject_config
.↩The
setup.py
file should be used only when custom scripting during the build is necessary. Examples are kept in this document to help people interested in maintaining or contributing to existing packages that usesetup.py
. Note that you can still keep most of configuration declarative insetup.cfg <declarative_config>
orpyproject.toml <pyproject_config>
and usesetup.py
only for the parts not supported in those files (e.g. C extensions).↩While the
[build-system]
table should always be specified in thepyproject.toml
file, support for adding package metadata and build configuration options via the[project]
and[tool.setuptools]
tables is still experimental and might change (or be completely removed) in future releases. See/userguide/pyproject_config
.↩The
setup.py
file should be used only when custom scripting during the build is necessary. Examples are kept in this document to help people interested in maintaining or contributing to existing packages that usesetup.py
. Note that you can still keep most of configuration declarative insetup.cfg <declarative_config>
orpyproject.toml <pyproject_config>
and usesetup.py
only for the parts not supported in those files (e.g. C extensions).↩While the
[build-system]
table should always be specified in thepyproject.toml
file, support for adding package metadata and build configuration options via the[project]
and[tool.setuptools]
tables is still experimental and might change (or be completely removed) in future releases. See/userguide/pyproject_config
.↩The
setup.py
file should be used only when custom scripting during the build is necessary. Examples are kept in this document to help people interested in maintaining or contributing to existing packages that usesetup.py
. Note that you can still keep most of configuration declarative insetup.cfg <declarative_config>
orpyproject.toml <pyproject_config>
and usesetup.py
only for the parts not supported in those files (e.g. C extensions).↩While the
[build-system]
table should always be specified in thepyproject.toml
file, support for adding package metadata and build configuration options via the[project]
and[tool.setuptools]
tables is still experimental and might change (or be completely removed) in future releases. See/userguide/pyproject_config
.↩The
setup.py
file should be used only when custom scripting during the build is necessary. Examples are kept in this document to help people interested in maintaining or contributing to existing packages that usesetup.py
. Note that you can still keep most of configuration declarative insetup.cfg <declarative_config>
orpyproject.toml <pyproject_config>
and usesetup.py
only for the parts not supported in those files (e.g. C extensions).↩While the
[build-system]
table should always be specified in thepyproject.toml
file, support for adding package metadata and build configuration options via the[project]
and[tool.setuptools]
tables is still experimental and might change (or be completely removed) in future releases. See/userguide/pyproject_config
.↩