2 Critical Python packaging tools

At last week’s Python Frederick meetup, I gave a talk on Python packaging. My aim was to cover how packaging works and how to build a basic package. Over the course of the talk, we used a couple of tools that I think are critical for releasing a Python package to PyPI. I’ll describe these tools and why I think they are critical.

tox

tox is a fantastic tool for testing packaging. With the tox command, a developer can build a package, install it into a virtual environment for a specific Python version, and run the package through its test suite.

The short version of running tox looks like:

$ tox -e py36

This command will run a package’s test suite against Python 3.6. I love it when commands are that elegant. To make that possible, the developer must tell tox how to run the test suite. This configuration is done in a tox.ini file. A minimal file could look like:

[tox]
envlist = py36

[testenv]
commands = python -m unittest discover \
    -s {envsitepackagesdir}/whirlygig

In this example, you would change whirlygig to the name of your project. This is enough information to inform tox about how to run your test suite.

I find that using tox saves me from hard to catch packaging bugs (did you know those exist?) and is generally awesome for testing against multiple versions of Python.

twine

twine is a critical tool in a packager’s toolbelt for one reason: it let’s you upload to PyPI over HTTPS. In contrast, python setup.py upload uses insecure HTTP for many versions of Python.

Even though it seems silly, you need a separate package to upload securely over HTTPS. I presume there are good reasons for that requirement that I’m unaware of.

python setup.py sdist bdist_wheel creates a dist directory with the packages to upload. (Ed. Note: Hello from 2021! The Python community has moved away from using setup.py directly. To build your packages instead, use a tool like build). You can perform your upload with:

$ twine upload dist/*

Summary

The Python ecosystem has excellent documentation about packaging at the Python Packaging User Guide. This post was meant to be a gentle introduction to a couple of very valuable tools when you want to work with packages.

(Yes, I know a “package” is technically called a “distribution” in proper Python lingo, but I used the term as it is more broadly accepted among many programming languages.)