Packaging & Publishing Highlights Summary
Every highlight bullet from the 9 pages in this section, gathered on one page and grouped by the page it came from.
- A build backend, not pip, decides how your source tree becomes an installable artifact - pip just orchestrates the call
- An sdist and a wheel solve different problems: one is a portable source snapshot, the other is a ready-to-install artifact
- Platform and ABI tags exist because a compiled wheel is only valid on the interpreter/OS/architecture combination it was built for
- Versioning, entry points, and publishing are metadata riding on top of this pipeline, not separate systems
- Native extensions don't change the pipeline - they add a compile step before the same wheel-shaped output
- Wheels install faster than sdists by skipping the build step
- src/ layout prevents accidental imports from repo root, industry standard
- Define your package version once in pyproject.toml using SemVer
- Test on TestPyPI sandbox before promoting to the live PyPI registry
- Include package data explicitly with force-include in pyproject.toml config
- Use OIDC trusted publishing in CI instead of hardcoded PyPI passwords
- Hatchling is the modern default build backend
- Missing packages config produces empty wheels
- Test wheels with pip install dist/*.whl before upload
- Use uv build to create both wheel and sdist files
- Use maturin for Rust extensions, setuptools for C
- Delete stale setup.py to prevent metadata conflicts
- MAJOR for breaking changes, MINOR for features, PATCH for bug fixes
- Breaking changes in MINOR versions damage consumer trust, always bump MAJOR
- Update CHANGELOG.md with every release so consumers assess upgrade risk
- Keep version in one source like pyproject.toml to prevent version drift
- Release 1.0.0 when your public API is stable and production-ready
- Use hatch-vcs or setuptools-scm to dynamically version from git tags
- Validate on TestPyPI before publishing to production
- Trusted publishing uses GitHub OIDC, no long-lived tokens
- Always publish wheel and sdist together, never source alone
- Bump version before publish, PyPI rejects duplicate versions
- Use env vars or trusted publishing only, never hardcoded tokens
- Include README and license metadata for complete PyPI page
- Entry points register CLI commands and plugin discovery hooks at install time
- Use [project.scripts] for console commands and [project.entry-points] for plugins
- Point entry points to callables, not modules, or they fail at runtime
- Use unique namespaced command names to avoid overwriting existing CLIs
- Lazy-load plugins when subcommands invoke them, not at import time
- Reinstall package after changing entry point config in pyproject.toml
- Native extensions compile Python to C or Rust for significant speed gains
- Use cibuildwheel in CI to automate platform-specific wheel builds for all targets
- Users pip install pre-built wheels without needing a compiler on their system
- Wheel tags encode Python version, ABI, and platform for proper PyPI distribution
- Building only on your dev machine breaks cross-platform installs, use cibuildwheel
- PyPI rejects manylinux-noncompliant wheels, use auditwheel to repair
- Use Docker for web apps, pipx for CLI tools, PyInstaller for desktop, PyPI for libraries
- PyInstaller bundles Python and dependencies into single executables, typically 50-200MB
- pipx isolates each CLI tool in its own virtual environment for cleaner PATH management
- Reduce Docker size with slim base images, multi-stage builds, and .dockerignore files
- Never ship secrets in Docker images; use environment variables and runtime secrets managers
- Publishing applications to PyPI is wrong; use Docker for services or pipx for CLIs instead
- Use src/ layout and pyproject.toml as your single source of truth
- Apply semantic versioning to libraries for predictable releases
- Test all packages on TestPyPI before production upload
- Use OIDC trusted publishing instead of password-based CI uploads
- Set requires-python to match your actual supported versions
- Never include secrets or API keys anywhere in package source
Revisado por Chris St. John·Última atualização: 31 de jul. de 2026