Home/Blog/Python Packaging: The Complete Guide to Building, Publishing, and Maintaining Packages
Software Engineering

Python Packaging: The Complete Guide to Building, Publishing, and Maintaining Packages

Master Python packaging from development to PyPI publication. Complete guide covering pyproject.toml, dependencies, versioning, testing, CLI tools, and documentation with links to 11 detailed tutorials.

By InventiveHQ Team
Python Packaging: The Complete Guide to Building, Publishing, and Maintaining Packages

Python packaging has evolved significantly, with modern tools like pyproject.toml replacing the fragmented landscape of setup.py, setup.cfg, and requirements.txt. This guide provides a comprehensive overview of the Python packaging ecosystem and connects you to detailed tutorials for each topic.

Why Packaging Matters

Poor packaging practices lead to common problems:

ProblemSymptomSolution
"Works on my machine"Different behavior across environmentsVirtual environments + pinned dependencies
Dependency conflictsPackage A needs X>=2.0, B needs X<2.0Proper dependency specification
Broken installationspip install failsCorrect package structure + metadata
Security vulnerabilitiesOutdated dependenciesAutomated updates + version policies
Lost codeCan't reproduce old versionProper versioning + PyPI publishing

The Python Packaging Landscape

┌─────────────────────────────────────────────────────────────────────┐
│                 Python Packaging Ecosystem                           │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐  │
│  │   CONFIGURE     │    │     BUILD       │    │   DISTRIBUTE    │  │
│  │                 │    │                 │    │                 │  │
│  │ pyproject.toml  │───▶│  wheel (.whl)   │───▶│     PyPI        │  │
│  │ requirements.txt│    │  sdist (.tar.gz)│    │  Private repos  │  │
│  │ setup.py (old)  │    │                 │    │  GitHub releases│  │
│  └─────────────────┘    └─────────────────┘    └─────────────────┘  │
│           │                      │                      │            │
│           ▼                      ▼                      ▼            │
│  ┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐  │
│  │  Build Backends │    │   Build Tools   │    │  Install Tools  │  │
│  │                 │    │                 │    │                 │  │
│  │ - hatchling     │    │ - build         │    │ - pip           │  │
│  │ - setuptools    │    │ - pip wheel     │    │ - pipx          │  │
│  │ - flit-core     │    │ - twine         │    │ - uv            │  │
│  │ - poetry-core   │    │                 │    │                 │  │
│  └─────────────────┘    └─────────────────┘    └─────────────────┘  │
│                                                                      │
│  ┌─────────────────────────────────────────────────────────────────┐│
│  │                    Environment Management                        ││
│  │  venv | virtualenv | conda | pyenv | poetry | pipenv            ││
│  └─────────────────────────────────────────────────────────────────┘│
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Quick Start Decision Guide

Which Configuration File?

Starting a new project?
│
├── Library (publish to PyPI)
│   └── Use: pyproject.toml (primary)
│           + requirements-dev.txt (dev dependencies)
│
├── Application (deploy to server)
│   └── Use: pyproject.toml (metadata + deps)
│           + requirements.txt (pinned versions)
│
└── Script or notebook
    └── Use: requirements.txt (simple dependency list)

For detailed guidance, see our pyproject.toml vs requirements.txt vs setup.py comparison.

Which Dependency Tool?

Project Type?
│
├── Simple project, familiar with pip
│   └── Use: pip + pip-tools
│
├── Want all-in-one solution
│   └── Use: Poetry
│
├── Data science / scientific computing
│   └── Use: conda
│
└── Enterprise with strict requirements
    └── Use: pip-tools or Poetry with lock files

Core Topics

1. Declaring Dependencies

The foundation of Python packaging is declaring what your project needs.

requirements.txt provides simple dependency lists:

requests>=2.28.0
click>=8.0.0
pydantic>=2.0

For a complete guide to requirements.txt syntax, version specifiers, and best practices, see our requirements.txt Complete Guide.

pyproject.toml is the modern standard:

[project]
dependencies = [
    "requests>=2.28.0",
    "click>=8.0.0",
    "pydantic>=2.0",
]

[project.optional-dependencies]
dev = ["pytest", "black", "mypy"]

For comprehensive pyproject.toml configuration, see our pyproject.toml Complete Guide.

2. Environment Isolation

Virtual environments prevent dependency conflicts between projects.

# Create environment
python -m venv .venv

# Activate (macOS/Linux)
source .venv/bin/activate

# Activate (Windows)
.venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

For in-depth coverage of venv, virtualenv, conda, and pyenv, see our Virtual Environments Guide.

3. Dependency Resolution

Lock files capture exact versions for reproducible builds:

# With pip-tools
pip-compile requirements.in -o requirements.txt

# With Poetry
poetry lock

# With Pipenv
pipenv lock

Compare dependency management tools in our Dependency Management Tools Guide.

4. Building Packages

Transform your source into distributable packages:

# Install build tool
pip install build

# Build wheel and sdist
python -m build

# Result:
# dist/my_package-1.0.0-py3-none-any.whl
# dist/my_package-1.0.0.tar.gz

5. Publishing to PyPI

Share your package with the world:

# Upload to PyPI
twine upload dist/*

# Or use trusted publishing (no tokens needed)
# Configure in GitHub Actions workflow

For complete publishing instructions including trusted publishing setup, see our Publishing to PyPI Guide.

6. Versioning

Communicate changes through version numbers:

# Semantic versioning
version = "1.2.3"  # MAJOR.MINOR.PATCH

# Calendar versioning
version = "2026.01.15"  # YYYY.MM.DD

Learn versioning strategies and changelog management in our Package Versioning Guide.

7. Testing Packages

Ensure your package works across Python versions:

# Run tests with tox
tox

# Or nox (Python-native)
nox

For multi-version testing strategies, see our Testing Python Packages Guide.

8. CLI Tools

Create installable command-line tools:

# pyproject.toml
[project.scripts]
my-tool = "my_package.cli:main"

Build CLI interfaces with Click or Typer. See our Building CLI Tools Guide.

9. Documentation

Generate beautiful docs from your code:

# Sphinx
sphinx-quickstart docs

# MkDocs
mkdocs new .

Learn documentation best practices in our Package Documentation Guide.

10. Private Repositories

Host packages internally for your organization:

# Configure pip for private repo
pip install --extra-index-url https://pypi.company.com/simple/ private-package

Set up private repositories with our Private Package Repositories Guide.

Beginner Level

Start with understanding how dependencies work:

1. requirements.txt Guide     → Understand basic dependency management
2. Virtual Environments Guide → Isolate project dependencies
3. pyproject.toml Guide       → Learn modern configuration

Intermediate Level

Build and share your own packages:

4. Comparison Guide           → Choose the right approach
5. Dependency Tools Guide     → Advanced dependency management
6. Versioning Guide           → Version your packages properly
7. Publishing Guide           → Share on PyPI

Advanced Level

Professional package development:

8. Testing Guide              → Multi-version testing
9. CLI Tools Guide            → Build command-line tools
10. Documentation Guide       → Generate professional docs
11. Private Repos Guide       → Enterprise distribution

Quick Reference: All Guides

GuideTopicBest For
requirements.txt GuideBasic dependency filesBeginners, simple projects
pyproject.toml GuideModern configurationAll projects
Comparison GuideChoosing config filesDecision making
Virtual Environments Guidevenv, conda, pyenvEnvironment setup
Dependency Tools Guidepip-tools, Poetry, PipenvDependency management
Versioning GuideSemVer, CalVer, changelogsRelease management
Publishing GuidePyPI, twine, CI/CDDistribution
Testing Guidepytest, tox, noxQuality assurance
CLI Tools GuideClick, Typer, argparseCommand-line tools
Documentation GuideSphinx, MkDocsDocumentation
Private Repos Guidedevpi, CodeArtifactEnterprise

Modern Package Structure

The recommended structure for a Python package in 2026:

my-package/
├── src/
│   └── my_package/
│       ├── __init__.py
│       ├── core.py
│       └── cli.py
├── tests/
│   ├── __init__.py
│   ├── test_core.py
│   └── test_cli.py
├── docs/
│   ├── index.md
│   └── api.md
├── .github/
│   └── workflows/
│       ├── test.yml
│       └── publish.yml
├── pyproject.toml
├── README.md
├── CHANGELOG.md
└── LICENSE

Minimal pyproject.toml

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

[project]
name = "my-package"
version = "1.0.0"
description = "A useful Python package"
readme = "README.md"
license = {text = "MIT"}
requires-python = ">=3.9"
authors = [{name = "Your Name", email = "[email protected]"}]
dependencies = [
    "requests>=2.28",
]

[project.optional-dependencies]
dev = ["pytest", "black", "mypy"]

[project.urls]
Homepage = "https://github.com/user/my-package"

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

Key Takeaways

  1. Use pyproject.toml as your single source of configuration for all new projects.

  2. Always use virtual environments to isolate project dependencies.

  3. Lock your dependencies with pip-tools, Poetry, or similar for reproducible builds.

  4. Follow semantic versioning for libraries, calendar versioning for applications.

  5. Test across Python versions with tox or nox before releasing.

  6. Automate publishing with GitHub Actions and trusted publishing.

  7. Document your package with Sphinx or MkDocs from the start.

Next Steps

  1. Start with our pyproject.toml Complete Guide to set up your project

  2. Set up proper environments with our Virtual Environments Guide

  3. When ready to share, follow our Publishing to PyPI Guide

Additional Resources

For more Python development guides, explore our complete Python packaging series.

Frequently Asked Questions

Find answers to common questions

Python packaging is the process of organizing, distributing, and installing Python code. Proper packaging makes your code installable via pip, shareable on PyPI, reproducible across environments, and maintainable long-term. It's essential for any project beyond a single script.

Use pyproject.toml as your primary configuration for all new projects. It handles project metadata, dependencies, build configuration, and tool settings in one file. Use requirements.txt alongside it for pinning exact versions in deployments or for compatibility with older tools.

PyPI (Python Package Index) is the official repository for Python packages. To publish: configure pyproject.toml, build with python -m build, and upload with twine or GitHub Actions trusted publishing. See our PyPI Publishing Guide for detailed steps.

For most projects, pip-tools offers simplicity with pip-compile and pip-sync. Poetry provides an all-in-one solution with better dependency resolution. Pipenv is good for applications but less suitable for libraries. Choose based on your project type and team preferences.

Use pyenv to install and switch between Python versions, combined with venv or virtualenv for project-specific environments. For data science, conda environments handle both Python versions and system dependencies well.

Use Semantic Versioning (MAJOR.MINOR.PATCH) for libraries where API stability matters. Use Calendar Versioning (2026.01) for applications or projects with regular release schedules. Automate version management with setuptools-scm or bump2version.

Use tox or nox to run tests against multiple Python versions automatically. Configure a test matrix in CI/CD (GitHub Actions, GitLab CI) to ensure compatibility. Always test against your minimum supported version and latest Python release.

Define console_scripts entry points in pyproject.toml pointing to your CLI function. Use Click or Typer for building the CLI interface. After pip install, your command becomes available system-wide.

Use docstrings (Google or NumPy style) in your code, then generate API documentation with Sphinx or MkDocs. Host on Read the Docs for automatic builds from git. Include a README, changelog, and examples in your repository.

Options include self-hosted (devpi, pypiserver), cloud-managed (AWS CodeArtifact, GCP Artifact Registry), or enterprise (JFrog Artifactory). Configure pip with --extra-index-url or [global] sections in pip.conf to use your private repository.

Engineering Excellence for Your Business

Our engineers build systems that scale. Clean architecture, comprehensive testing, and security-first development.