|
4 | 4 | Tool recommendations
|
5 | 5 | ====================
|
6 | 6 |
|
7 |
| -If you're familiar with Python packaging and installation, and just want to know |
8 |
| -what tools are currently recommended, then here it is. |
| 7 | +The Python packaging landscape consists of many different tools. For many tasks, |
| 8 | +the :term:`Python Packaging Authority <Python Packaging Authority (PyPA)>` |
| 9 | +(PyPA, the working group which encompasses many packaging tools and |
| 10 | +maintains this guide) purposefully does not make a blanket recommendation; for |
| 11 | +example, the reason there are many build backends is that the landscape was |
| 12 | +opened up in order to enable the development of new backends serving certain users' |
| 13 | +needs better than the previously unique backend, setuptools. This guide does |
| 14 | +point to some tools that are widely recognized, and also makes some |
| 15 | +recommendations of tools that you should *not* use because they are deprecated |
| 16 | +or insecure. |
| 17 | + |
| 18 | + |
| 19 | +Virtual environments |
| 20 | +==================== |
| 21 | + |
| 22 | +The standard tools to create and use virtual environments manually are |
| 23 | +:ref:`virtualenv` (PyPA project) and :doc:`venv <python:library/venv>` (part of |
| 24 | +the Python standard library, though missing some features of virtualenv). |
| 25 | + |
| 26 | + |
| 27 | +Installing packages |
| 28 | +=================== |
| 29 | + |
| 30 | +:ref:`Pip` is the standard tool to install packages from :term:`PyPI <Python |
| 31 | +Package Index (PyPI)>`. You may want to read pip's recommendations for |
| 32 | +:doc:`secure installs <pip:topics/secure-installs>`. Pip is available by default |
| 33 | +in most Python installations through the standard library package |
| 34 | +:doc:`ensurepip <python:library/ensurepip>`. |
| 35 | + |
| 36 | +Alternatively, consider :ref:`pipx` for the specific use case of installing Python |
| 37 | +applications that are distributed through PyPI and run from the command line. |
| 38 | +Pipx is a wrapper around pip and venv that installs each |
| 39 | +application into a dedicated virtual environment. This avoids conflicts between |
| 40 | +the dependencies of different applications, and also with system-wide applications |
| 41 | +making use of the same Python interpreter (especially on Linux). |
| 42 | + |
| 43 | +For scientific software specifically, consider :ref:`Conda` or :ref:`Spack`. |
| 44 | + |
| 45 | +.. todo:: Write a "pip vs. Conda" comparison, here or in a new discussion. |
| 46 | + |
| 47 | +Do **not** use ``easy_install`` (part of :ref:`setuptools`), which is deprecated |
| 48 | +in favor of pip (see :ref:`pip vs easy_install` for details). Likewise, do |
| 49 | +**not** use ``python setup.py install`` or ``python setup.py develop``, which |
| 50 | +are also deprecated (see :ref:`setup-py-deprecated` for background and |
| 51 | +:ref:`modernize-setup-py-project` for migration advice). |
| 52 | + |
| 53 | + |
| 54 | +Lock files |
| 55 | +========== |
| 56 | + |
| 57 | +:ref:`pip-tools` and :ref:`Pipenv` are two recognized tools to create lock |
| 58 | +files, which contain the exact versions of all packages installed into an |
| 59 | +environment, for reproducibility purposes. |
| 60 | + |
| 61 | + |
| 62 | +Build backends |
| 63 | +============== |
| 64 | + |
| 65 | +.. important:: |
9 | 66 |
|
| 67 | + Please, remember: this document does not seek to steer the reader towards |
| 68 | + a particular tool, only to enumerate common tools. Different use cases often |
| 69 | + need specialized workflows. |
10 | 70 |
|
11 |
| -Application dependency management |
12 |
| -================================= |
| 71 | +Popular :term:`build backends <build backend>` for pure-Python packages include, |
| 72 | +in alphabetical order: |
13 | 73 |
|
14 |
| -* Use :ref:`pip` in a `secure manner`_ to install a Python application and its |
15 |
| - dependencies during deployment. |
| 74 | +- :doc:`Flit-core <flit:pyproject_toml>` -- developed with but separate from :ref:`Flit`. |
| 75 | + A minimal and opinionated build backend. It does not support plugins. |
16 | 76 |
|
17 |
| -* Use :ref:`virtualenv` or :doc:`venv <python:library/venv>` to isolate |
18 |
| - application-specific dependencies from a shared Python installation. [4]_ |
| 77 | +- Hatchling_ -- developed with but separate from :ref:`Hatch`. Supports plugins. |
19 | 78 |
|
20 |
| -* Use `pip-tools`_, :ref:`pipenv`, or `poetry`_ to generate the fully-specified |
21 |
| - application-specific dependencies, when developing Python applications. |
| 79 | +- PDM-backend_ -- developed with but separate from :ref:`PDM`. Supports plugins. |
22 | 80 |
|
23 |
| -.. _secure manner: https://pip.pypa.io/en/latest/topics/secure-installs/ |
24 |
| -.. _pip-tools: https://github.com/jazzband/pip-tools |
25 |
| -.. _Poetry: https://python-poetry.org/ |
| 81 | +- Poetry-core_ -- developed with but separate from :ref:`Poetry`. Supports |
| 82 | + plugins. |
26 | 83 |
|
27 |
| -Installation tool recommendations |
28 |
| -================================= |
| 84 | + Unlike other backends on this list, Poetry-core does not support the standard |
| 85 | + :ref:`[project] table <writing-pyproject-toml>` (it uses a different format, |
| 86 | + in the ``[tool.poetry]`` table). |
29 | 87 |
|
30 |
| -* Use :ref:`pip` to install Python :term:`packages <Distribution Package>` from |
31 |
| - :term:`PyPI <Python Package Index (PyPI)>`. [1]_ [2]_ Depending on how :ref:`pip` |
32 |
| - is installed, you may need to also install :ref:`wheel` to get the benefit |
33 |
| - of wheel caching. [3]_ |
| 88 | +- :ref:`setuptools`, which used to be the only build backend. Supports plugins. |
34 | 89 |
|
35 |
| -* Use :ref:`virtualenv` or :doc:`venv <python:library/venv>` to isolate |
36 |
| - project-specific dependencies from a shared Python installation. [4]_ |
| 90 | + .. caution:: |
37 | 91 |
|
38 |
| -* If you're looking for management of fully integrated cross-platform software |
39 |
| - stacks, consider: |
| 92 | + If you use setuptools, please be aware that some features that predate |
| 93 | + standardisation efforts are now deprecated and only *temporarily kept* |
| 94 | + for compatibility. |
40 | 95 |
|
41 |
| - * :ref:`buildout`: primarily focused on the web development community |
| 96 | + In particular, do **not** use direct ``python setup.py`` invocations. On the |
| 97 | + other hand, configuring setuptools with a :file:`setup.py` file is still fully |
| 98 | + supported, although it is recommended to use the modern :ref:`[project] table |
| 99 | + in pyproject.toml <writing-pyproject-toml>` (or :file:`setup.cfg`) whenever possible and keep |
| 100 | + :file:`setup.py` only if programmatic configuration is needed. See |
| 101 | + :ref:`setup-py-deprecated`. |
42 | 102 |
|
43 |
| - * :ref:`spack`, :ref:`hashdist`, or :ref:`conda`: primarily focused |
44 |
| - on the scientific community. |
| 103 | + Other examples of deprecated features you should **not** use include the |
| 104 | + ``setup_requires`` argument to ``setup()`` (use the :ref:`[build-system] table |
| 105 | + <pyproject-guide-build-system-table>` in :file:`pyproject.toml` instead), and |
| 106 | + the ``easy_install`` command (cf. :ref:`pip vs easy_install`). |
45 | 107 |
|
| 108 | +Do **not** use :ref:`distutils`, which is deprecated, and has been removed from |
| 109 | +the standard library in Python 3.12, although it still remains available from |
| 110 | +setuptools. |
46 | 111 |
|
47 |
| -Packaging tool recommendations |
48 |
| -============================== |
| 112 | +For packages with :term:`extension modules <extension module>`, it is best to use |
| 113 | +a build system with dedicated support for the language the extension is written in, |
| 114 | +for example: |
49 | 115 |
|
50 |
| -* Use :ref:`setuptools` to define projects. [5]_ [6]_ |
| 116 | +- :ref:`setuptools` -- natively supports C and C++ (with third-party plugins for Go and Rust), |
| 117 | +- :ref:`meson-python` -- C, C++, Fortran, Rust, and other languages supported by Meson, |
| 118 | +- :ref:`scikit-build-core` -- C, C++, Fortran, and other languages supported by CMake, |
| 119 | +- :ref:`maturin` -- Rust, via Cargo. |
51 | 120 |
|
52 |
| -* Use :ref:`build` to create :term:`Source Distributions |
53 |
| - <Source Distribution (or "sdist")>` and :term:`wheels <Wheel>`. |
54 | 121 |
|
55 |
| -If you have binary extensions and want to distribute wheels for multiple |
56 |
| -platforms, use :ref:`cibuildwheel` as part of your CI setup to build |
57 |
| -distributable wheels. |
| 122 | +Building distributions |
| 123 | +====================== |
58 | 124 |
|
59 |
| -* Use `twine <https://pypi.org/project/twine>`_ for uploading distributions |
60 |
| - to :term:`PyPI <Python Package Index (PyPI)>`. |
| 125 | +The standard tool to build :term:`source distributions <source distribution (or |
| 126 | +"sdist")>` and :term:`wheels <wheel>` for uploading to PyPI is :ref:`build`. It |
| 127 | +will invoke whichever build backend you :ref:`declared |
| 128 | +<pyproject-guide-build-system-table>` in :file:`pyproject.toml`. |
61 | 129 |
|
| 130 | +Do **not** use ``python setup.py sdist`` and ``python setup.py bdist_wheel`` for |
| 131 | +this task. All direct invocations of :file:`setup.py` are :ref:`deprecated |
| 132 | +<setup-py-deprecated>`. |
62 | 133 |
|
63 |
| -Publishing platform migration |
64 |
| -============================= |
| 134 | +If you have :term:`extension modules <extension module>` and want to distribute |
| 135 | +wheels for multiple platforms, use :ref:`cibuildwheel` as part of your CI setup |
| 136 | +to build distributable wheels. |
65 | 137 |
|
66 |
| -The original Python Package Index implementation (previously hosted at |
67 |
| -`pypi.python.org <https://pypi.python.org>`_) has been phased out in favour |
68 |
| -of an updated implementation hosted at `pypi.org <https://pypi.org>`_. |
69 | 138 |
|
70 |
| -See :ref:`Migrating to PyPI.org` for more information on the status of the |
71 |
| -migration, and what settings to change in your clients. |
| 139 | +Uploading to PyPI |
| 140 | +================= |
72 | 141 |
|
73 |
| ----- |
| 142 | +For projects hosted on GitHub, it is recommended to use the :ref:`trusted publishing |
| 143 | +<trusted-publishing>`, which allows the package to be securely uploaded to PyPI |
| 144 | +from a GitHub Actions job. (This is not yet supported on software forges other |
| 145 | +than GitHub.) |
74 | 146 |
|
75 |
| -.. [1] There are some cases where you might choose to use ``easy_install`` (from |
76 |
| - :ref:`setuptools`), e.g. if you need to install from :term:`Eggs <Egg>` |
77 |
| - (which pip doesn't support). For a detailed breakdown, see :ref:`pip vs |
78 |
| - easy_install`. |
| 147 | +The other available method is to upload the package manually using :ref:`twine`. |
79 | 148 |
|
80 |
| -.. [2] The acceptance of :pep:`453` means that :ref:`pip` |
81 |
| - will be available by default in most installations of Python 3.4 or |
82 |
| - later. See the :pep:`rationale section <453#rationale>` from :pep:`453` |
83 |
| - as for why pip was chosen. |
| 149 | +**Never** use ``python setup.py upload`` for this task. In addition to being |
| 150 | +:ref:`deprecated <setup-py-deprecated>`, it is insecure. |
84 | 151 |
|
85 |
| -.. [3] `get-pip.py <https://github.com/pypa/get-pip/#readme>`_ and |
86 |
| - :ref:`virtualenv` install |
87 |
| - :ref:`wheel`, whereas :ref:`ensurepip` and :ref:`venv <venv>` do not |
88 |
| - currently. Also, the common "python-pip" package that's found in various |
89 |
| - linux distros, does not depend on "python-wheel" currently. |
90 | 152 |
|
91 |
| -.. [4] Beginning with Python 3.4, ``venv`` will create virtualenv environments |
92 |
| - with ``pip`` installed, thereby making it an equal alternative to |
93 |
| - :ref:`virtualenv`. However, using :ref:`virtualenv` will still be |
94 |
| - recommended for users that need cross-version consistency. |
| 153 | +Workflow tools |
| 154 | +============== |
95 | 155 |
|
96 |
| -.. [5] Although you can use pure :ref:`distutils` for many projects, it does not |
97 |
| - support defining dependencies on other projects and is missing several |
98 |
| - convenience utilities for automatically populating distribution metadata |
99 |
| - correctly that are provided by ``setuptools``. Being outside the |
100 |
| - standard library, ``setuptools`` also offers a more consistent feature |
101 |
| - set across different versions of Python, and (unlike ``distutils``), |
102 |
| - recent versions of ``setuptools`` support all of the modern metadata |
103 |
| - fields described in :ref:`core-metadata`. |
| 156 | +These tools are environment managers that automatically manage virtual |
| 157 | +environments for a project. They also act as "task runners", allowing you to |
| 158 | +define and invoke tasks such as running tests, compiling documentation, |
| 159 | +regenerating some files, etc. Some of them provide shortcuts for building |
| 160 | +distributions and uploading to PyPI, and some support lock files for |
| 161 | +applications. They often call the tools mentioned above under the hood. In |
| 162 | +alphabetical order: |
104 | 163 |
|
105 |
| - Even for projects that do choose to use ``distutils``, when :ref:`pip` |
106 |
| - installs such projects directly from source (rather than installing |
107 |
| - from a prebuilt :term:`wheel <Wheel>` file), it will actually build |
108 |
| - your project using :ref:`setuptools` instead. |
| 164 | +- :ref:`Flit`, |
| 165 | +- :ref:`Hatch`, |
| 166 | +- :doc:`nox <nox:index>`, |
| 167 | +- :ref:`PDM`, |
| 168 | +- :ref:`Pipenv`, |
| 169 | +- :ref:`Poetry`, |
| 170 | +- :doc:`tox <tox:index>`. |
109 | 171 |
|
110 |
| -.. [6] `distribute`_ (a fork of setuptools) was merged back into |
111 |
| - :ref:`setuptools` in June 2013, thereby making setuptools the default |
112 |
| - choice for packaging. |
113 | 172 |
|
114 |
| -.. _distribute: https://pypi.org/project/distribute |
| 173 | +.. _hatchling: https://pypi.org/project/hatchling/ |
| 174 | +.. _pdm-backend: https://backend.pdm-project.org |
| 175 | +.. _poetry-core: https://pypi.org/project/poetry-core/ |
0 commit comments