Modern Python Packaging

Create and distribute Python packages with pyproject.toml and modern tooling

Modern Python Packaging

The Python packaging landscape has evolved. Here's the modern approach using pyproject.toml.

Project Structure

my_package/
├── pyproject.toml
├── README.md
├── src/
│   └── my_package/
│       ├── __init__.py
│       └── core.py
└── tests/
    └── test_core.py

pyproject.thumb

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-package"
version = "0.1.0"
description = "A useful package"
readme = "README.md"
requires-python = ">=3.11"
license = {text = "MIT"}
authors = [
    {name = "Your Name", email = "you@example.com"}
]
dependencies = [
    "requests>=2.28",
    "pydantic>=2.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0",
    "mypy>=1.0",
    "ruff>=0.1",
]

[project.scripts]
my-cli = "my_package.cli:main"

Building and Publishing

# Install build tools
pip install build twine

# Build package
python -m build

# Upload to PyPI
twine upload dist/*

Development Workflow

# Create virtual environment
python -m venv .venv
source .venv/bin/activate

# Install in editable mode with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Type check
mypy src/

# Lint
ruff check src/

Tools Comparison

Tools Purpose
hatch Build, publish, manage environments
poetry Dependency management + building
pdm PEP 582 local packages
flit Simple publishing