Make a python package pip installable

Alexander Fengler · March 19, 2023

Basic setup

At best start from a fresh conda / mamba environment and make sure the setuptools package (usually is) as well as the twine package (usually is not) are available. If not then simply type,

pip install setuptools
pip install twine

Make a distribution

Two steps to making a source distribution (the file which you will upload to PyPI later). First, check if your setup.py file provides all necessary meta-data to make PyPI happy. Run this check with,

python setup.py check

If no errors are raise, then proceed with creating the source distribution,

python setup.py sdist

This will create (if not available) a dist folder and a tar.gz file with a file name roughly like packagename-version.tar.gz.

Test upload

We can now test-run an upload to PyPI via the TestPyPI server (Test Python Package Index).
To upload our just-created source distribution, we will type the following in the terminal.

twine upload --repository-url hhtps://test.pypi.org/legacy/ dist/packagename-version.tar.gz

Test install

To test-run an install from TestPyPI, we type,

pip install --index-url https://test.pypi.org/simple/ packagename --user

One may run into issues with dependencies, in which case the extra argument --extra-index-url https://pypi.org/simple can (it did in my case) help. The full command in this case:

pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ packagename --user

The real thing

If the test install suceeded (consider trying it in fresh conda / mamba environments across a few python versions), we can now confidently upload our distribution to to PyPI. Simply type,

twine upload dist/packagename-version.tar.gz

You will be asked for your username and password. Once the upload finished, you can try installing your package via the standard pip install command like so,

pip install packagename

MANIFEST

The sdist command, will not necessarily include all the files in your package folder that are important for an actual installation of your package (e.g. if you have a src subfolder which includes a few .c or .pyx files). To explicitly include (and exclude) specific files and subfolders in the source distribution, you need to add a MANIFEST.in file. The concent of these MANIFEST.in files follows a specific syntax, which you can find in the documentation.

Below an example:

recursive-include docs
include README.md LICENSE
include mypackage *.py
include src/*.pyx
include notebooks/*
global-exclude .gitignore
global-exclude .git
global-exclude *~
global-exclude *.pyc
global-exclude .#*

Some Credits

This tutorial is a slightly adapted, mostly much reduced version of this excellent blog post.

Twitter, Facebook