Chapter 18: Packaging & Distribution

Structure, build and publish your Python projects using setuptools, pyproject.toml, wheels and Twine.

Download chapter18.py

Objectives

1. Project Structure

Typical layout:

myproject/
├── src/
│   └── mypackage/
│       ├── __init__.py
│       └── module.py
├── README.md
├── LICENSE
├── setup.py
└── pyproject.toml

2. setup.py with setuptools

from setuptools import setup, find_packages

setup(
    name="mypackage",
    version="0.1.0",
    author="Your Name",
    description="A brief description",
    packages=find_packages("src"),
    package_dir={"": "src"},
    install_requires=[
        "requests>=2.0"
    ],
    entry_points={
        "console_scripts": [
            "mycmd = mypackage.module:main"
        ]
    },
)

3. pyproject.toml (PEP 517/518)

[build-system]
requires = ["setuptools>=42","wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "mypackage"
version = "0.1.0"
description = "A brief description"
authors = [{name="Your Name", email="you@example.com"}]
dependencies = ["requests>=2.0"]

4. Building Distributions

# install build tool (optional)
python -m pip install --upgrade build

# generate sdist and wheel
python -m build
# outputs in dist/: mypackage-0.1.0.tar.gz and .whl

5. Publishing to PyPI

# install twine
python -m pip install --upgrade twine

# upload to Test PyPI
python -m twine upload --repository testpypi dist/*

# install from Test PyPI to test
pip install --index-url https://test.pypi.org/simple/ mypackage

# upload to official PyPI
python -m twine upload dist/*

Exercises

  1. Create a minimal package in src/, write setup.py and build an sdist.
  2. Add an entry_point console_script and test it after installing locally.
  3. Convert setup.py metadata into pyproject.toml and rebuild.
  4. Publish your package to Test PyPI and install it from there.