Python Packaging Tools (original) (raw)

Tools for building your package#

There are a several different build tools that you can use to create your Python package’s sdist and wheel distributions. Below, we discuss the features, benefits and limitations of the most commonly used Python packaging tools. We focus on pure-python packages in this guide. However, we also highlight tools that currently support packages with C/C++ and other language extensions.

Decision tree diagram showing the various front and back end packaging tools. You can decide what packaging tool to use by thinking about what features you need. PDM and Hatch are  currently the most flexible tools as they also using different build back-ends. As such currently PDM and Hatch are the tools we think beginners might appreciate most with Poetry being a close second. Poetry is nice for pure Python projects.

Diagram showing the different front end build tools available to use in the Python package ecosystem that you can select from. We selected tools to include in this diagram based upon the PyPI survey which helped us understand the most populate tools in the ecosystem. Each tool has different features as highlighted below.#

If you want to know more about Python packages that have extensions written in other languages, check out the page on complex package builds.

Tools that we review here#

In this section we have selected tools that were returned as the most popular packaging tools in the PyPA survey. You will learn more about the following tools on this page:

Summary of tools Hatch vs. PDM vs. Poetry (and setuptools)#

If you are looking for a quick summary, read below.

Below are some features that Hatch and PDM offer that Poetry does not.

PDM:

Hatch:

Build front-end vs. build back-end tools#

To better understand your options, when it comes to building a Python package, it’s important to first understand the difference between a build tool front-end and build back-end.

Build back-ends#

Most packaging tools have a back-end build tool that builds you package and creates associated(sdist and wheel) distribution files. Some tools, such as Flit, only support pure-Python package builds. A pure-Python build refers to a package build that does not have extensions that are written in another programming language (such as C or C++).

Other packages that have C and C++ extensions (or that wrap other languages such as fortran) require additional code compilation steps when built. Back-ends such as setuptools.build, meson.buildand scikit-build support complex builds with custom steps. If your build is particularly complex (i.e. you have more than a few C/C++extensions), then we suggest you use meson.build or scikit-build.

Python package build front-ends#

A packaging front-end tool refers to a tool that makes it easier for you to perform common packaging tasks using similar commands. These tasks include:

There are several Python packaging tools that you can use for pure Python builds. Each front-end tool discussed below supports a slightly different set of Python packaging tasks.

For instance, you can use the packaging tools Flit, Hatch or PDMto both build and publish your package to PyPI. However while Hatch andPDM support versioning and environment management, Flit does not. If you want a tool that supports dependency locking, you can use PDM or Poetry but not Hatch. If you only need to build your package’s sdist and wheel distribution files, then you can stick with PyPA’s Build. You’d then use Twine to publish to PyPI.

Note

If you are using Setuptools, there is no default user-friendly build front-end that performs multiple tasks. You will need to use build to build your package and twine to publish to PyPI.

Example build steps that can be simplified using a front-end tool#

Below, you can see how a build tool streamlines your packaging experience. Example to build your package with Hatch:

Build your sDist and .whl files

hatch build

Example to publish to PyPI:

hatch publish --repo test

Example build steps using the setuptools back-end and build:

Build the package

python3 -m build

Publish to test PyPI using twine

twine upload -r testpypi dist/*

Choosing a build back-end#

Most front-end packaging tools have their own back-end build tool. The build tool creates your package’s (sdist and wheel) distribution files. For pure Python packages, the main difference between the different build back-ends discussed below is:

Build back-end support for non pure-python packages#

It is important to note that some build back-ends, such as Flit-core, only support pure Python builds. Other back-ends support C and C++ extensions as follows:

While we won’t discuss more complex builds below, we will identify which tools have documented support for C / C++ extensions.

An ecosystem of Python build tools#

Below we introduce several of the most commonly used Python packaging build front-end tools. We highlight the features that each tool offers as a way to help you decide what tool might be best for your workflow.

We do not suggest using setuptools

We suggest that you pick one of the modern tools listed above rather than setuptools because setuptools will require some additional knowledge to set up correctly.

We review setuptools as a back-end because it is still popular. However it is not the most user friendly option.

The most commonly used tools in the ecosystem are setuptools back-end (with build) and Poetry (a front end tool with numerous features and excellent documentation).

Graph showing the results of the 2022 PyPA survey of Python packaging tools. On the x axis is percent response and on the y axis are the tools.

The Python developers survey results (n=>8,000 PyPI users) show setuptools and poetry as the most commonly used Python packaging tools. The core tools that we’ve seen being used in the scientific community are included here. You can view the full survey results by clicking here. NOTE: this data represent maintainers across domains and is likely heavily represented by those in web development. So this represents a snapshot across the broader Python ecosystem.#

Chose a build workflow tool#

The tools that we review below include:

When you are selecting a tool, you might consider this general workflow of questions:

  1. Is your tool pure python? Yes? You can use any tool that you wish! Pick the tool that has the features that you want to use in your build workflow. We suggest:
  1. Does your tool have a few C or C++ extensions? Great, we suggest usingPDM for the time being. It is the only tool in the list below that has both documented workflow to support such extensions and support for other back-ends in the case that build hooks are not enough for your workflow. PDM supports other back-ends such as scikit-build and meson-python that will allow you to fully customize your package’s build.

NOTE: You can also use Hatch for non pure python builds. Hatch, similar to PDM, allows you to write your own build hooks or plugins to support custom build steps. But currently, hatch does not support other build back ends. Many of the core scientific packages are moving to meson-python to build their packages. Thus, we appreciate that PDM can work with meson-python specifically.

Python packaging tools summary#

Below, we summarize features offered by the most popular build front end tools. It is important to keep in mind that these front-end tools remove the need to use other core tools in your workflow. For example if you use setuptools, you will need to also use Build and Twine to build your package and publish to PyPI. But if you use Poetry, Hatch or PDM you can do all of those things using the same tool (e.g. hatch build, hatch publish or pdm build, pdm publish).

Note that because setuptools does not offer a front-end interface, it is not included in the table.

Package tool features table#

Notes:

PDM#

PDM is a Python packaging and dependency management tool. PDM supports builds for pure Python projects. It also provides multiple layers of support for projects that have C and C++ extensions.

PDM support for C and C++ extensions

PDM supports using the PDM-back-end and setuptools at the same time. This means that you can run setuptools to compile and build C extensions. PDM’s build back-end receives the compiled extension files (.so, .pyd) and packages them with the pure Python files.

PDM Features#

PDM vs. Poetry

The functionality of PDM is similar to Poetry. However, PDM also offers additional, documented support for C extensions and version control based versioning. As such, PDM is preferred for those working on non pure-Python packages.

If you are deciding between the Poetry and PDM, a smaller difference is the default way that dependencies are added to your pyproject.toml file.

Finally there are some nuanced differences in how both tools create lock files which we will not go into detail about here.

Challenges with PDM#

PDM is a full-featured packaging tool. However it is not without challenges:

You can view an example of a package that uses PDM here. The README file for this directly provides you with an overview of what the PDM command line interface looks like when you use it.

Flit#

Flit is a no-frills, streamlined packaging tool that supports modern Python packaging standards. Flit is a great choice if you are building a basic package to use in a local workflow that doesn’t require any advanced features. And if your package structure is already created. More on that below.

Flit Features#

NOTE: If you are using the most current version of pip, it supports both a symlink approach flit install -s and python -m pip install -e .

Why you might not want to use Flit#

Because Flit is no frills, it is best for basic, quick builds. If you are a beginner you may want to select Hatch or PDM which will offer you more support in common operations.

You may NOT want to use flit if:

Hatch#

Hatch, similar to Poetry and PDM, provides a unified command line interface. To separate Hatch from Poetry and PDM, it also provides an environment manager for testing that will make it easier for you to run tests locally across different versions of Python. It also offers a nox / makefile like feature that allows you to create custom build workflows such as building your documentation locally. This means that you could potentially drop a tool like Make or Nox from your workflow and use Hatch instead.

Hatch features#

There is some argument about this approach placing a burden on maintainers to create a custom build system. But others appreciate the flexibility. The Hatch build hook approach is also comparable with the features offered by PDM.

Why you might not want to use Hatch#

There are a few features that hatch is missing that may be important for some. These include:

Poetry#

Poetry is a full-featured build tool. It is also the second most popular front-end packaging tool (based upon the PyPA survey). Poetry is user-friendly and has clean and easy-to-read documentation.

Note

While some have used Poetry for Python builds with C/C++ extensions, this support is currently undocumented. Thus, we don’t recommend using Poetry for more complex builds.

Poetry features#

Challenges with Poetry#

Some challenges of Poetry include:

Poetry is a popular packaging tool and introduced many very useful features. However, if you decide to use it, then use caution when adding dependencies as Poetry’s approach to pinning can be problematic for many builds. If you use Poetry, we strongly suggest that you override the default upper bound dependency option.

Challenges with Poetry dependency pinning

By default, Poetry pins dependencies using ^ by default. This ^ symbol means that there is an “upper bound” to the dependency. Thus poetry won’t bump a dependency version to a new major version. Thus, if your package uses a dependency that is at version 1.2.3, Poetry will never bump the dependency to 2.0 even if there is a new major version of the package. Poetry will instead bump up to 1.9.x.

Poetry does this because it adheres to strict semantic versioning which states that a major version bump (from 1.0 to 2.0 for example) means there are breaking changes in the tool. However, not all tools follow strict semantic versioning.This approach has been found to be problematic by many of our core scientific packages.

This approach also won’t support others ways of versioning tools, for instance, some tools use calver which creates new versions based on the date.

Using Setuptools Back-end for Python Packaging with Build Front-end#

Setuptools is the most mature Python packaging build tool with development dating back to 2009 and earlier. Setuptools also has the largest number of community users (according to the PyPA survey). Setuptools does not offer a user front-end like Flit, Poetry and Hatch offer. As such you will need to use other tools such as build to create your package distributions and twine to publish to PyPI.

While setuptools is the most commonly used tool, we encourage package maintainers to consider using a more modern tool for packaging such as Poetry, Hatch or PDM.

We discuss setuptools here because it’s commonly found in the ecosystem and contributors may benefit from understanding it.

Setuptools Features#

Some of features of setuptools include:

Challenges using setuptools#

Setuptools has a few challenges:

There are also some problematic default settings that users should be aware of when using setuptools. For instance: