Costruisci pacchetti Python: Guida dallo sviluppo a PyPI
Padroneggiare l'imballaggio Python dal codice al deployment su PyPI
Packaging Python ha evoluto significativamente, con strumenti moderni e standard che rendono più facile mai distribuire il tuo codice.
Questo tutorial ti guida attraverso la creazione di pacchetti Python professionali e la loro pubblicazione su PyPI. Se sei nuovo a Python o hai bisogno di un riferimento rapido, consulta il nostro Python Cheatsheet per aggiornarti sui fondamenti di Python.

Perché Pacchettizzare il Tuo Codice Python?
Pacchettizzare il tuo progetto Python offre diversi vantaggi:
- Riusabilità: Condividi il codice tra diversi progetti senza copiare e incollare
- Distribuzione: Permette ad altri di installare il tuo codice con un semplice
pip install - Gestione delle dipendenze: Specifica chiaramente e gestisci le dipendenze
- Versioning: Traccia le release e mantieni la compatibilità all’indietro
- Standard Professionali: Segui le best practice della comunità Python
- Documentazione: La struttura incoraggia una corretta documentazione e test
Struttura Moderna di un Pacchetto Python
Un pacchetto ben organizzato segue questa struttura:
my-package/
├── src/
│ └── mypackage/
│ ├── __init__.py
│ ├── core.py
│ └── utils.py
├── tests/
│ ├── __init__.py
│ └── test_core.py
├── docs/
│ └── index.md
├── .github/
│ └── workflows/
│ └── publish.yml
├── pyproject.toml
├── README.md
├── LICENSE
└── .gitignore
La src-layout è ora preferibile rispetto alla layout piatta perché:
- Previene importazioni accidentali di codice non installato durante lo sviluppo
- Rende i test più affidabili costringendo all’installazione
- Separa chiaramente il codice sorgente da altri file del progetto
Quando organizziamo la struttura interna del pacchetto, considera l’applicazione di principi di architettura pulita per rendere il tuo codice più mantenibile e testabile. La nostra guida su Python Design Patterns for Clean Architecture copre i principi SOLID, l’iniezione di dipendenze e i pattern di architettura a strati che funzionano eccellentemente con i pacchetti Python.
Il File pyproject.toml: Configurazione Moderna
pyproject.toml (PEP 518, 621) è lo standard moderno per la configurazione dei progetti Python, sostituendo l’obsoleto setup.py:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "mypackage"
version = "0.1.0"
description = "A fantastic Python package"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
{name = "Your Name", email = "you@example.com"}
]
keywords = ["example", "tutorial", "package"]
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
[project.optional-dependencies]
dev = [
"pytest>=7.4.0",
"black>=23.0.0",
"flake8>=6.0.0",
"mypy>=1.5.0",
]
docs = [
"sphinx>=7.0.0",
"sphinx-rtd-theme>=1.3.0",
]
[project.urls]
Homepage = "https://github.com/yourusername/mypackage"
Documentation = "https://mypackage.readthedocs.io"
Repository = "https://github.com/yourusername/mypackage"
Issues = "https://github.com/yourusername/mypackage/issues"
[project.scripts]
mypackage-cli = "mypackage.cli:main"
[tool.setuptools.packages.find]
where = ["src"]
Sezioni Principali di Configurazione
- build-system: Specifica il backend di costruzione (setuptools, hatchling, poetry-core, flit-core)
- project: Metadati principali e dipendenze
- project.optional-dependencies: Dipendenze extra per funzionalità aggiuntive (dev, docs, testing)
- project.scripts: Punti di ingresso per il comando della riga di comando
- tool.*: Configurazione specifica per gli strumenti (black, pytest, mypy, ecc.)
Scegliere un Backend di Costruzione
Setuptools (Scelta Standard)
L’opzione più utilizzata e compatibile:
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
Vantaggi: Compatibilità universale, funzionalità estese, ecosistema grande Svantaggi: Configurazione più verbosa, più lenta rispetto alle alternative moderne
Hatchling (Modern e Veloce)
Backend moderno e leggero:
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Vantaggi: Costruzioni veloci, configurazione semplice, buoni valori di default Svantaggi: Meno plugin rispetto a setuptools
Poetry (Completo)
Gestione completa delle dipendenze e dell’ambiente:
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "mypackage"
version = "0.1.0"
description = "A fantastic Python package"
authors = ["Your Name <you@example.com>"]
[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.28.0"
Vantaggi: Risoluzione delle dipendenze, file di blocco, workflow integrato Svantaggi: Workflow diverso, superficie strumenti più grande
Flit (Minimalista)
Strumento semplice per pacchetti semplici:
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"
Vantaggi: Estremamente semplice, configurazione minima Svantaggi: Funzionalità limitate per pacchetti complessi
Costruire il Tuo Pacchetto
Installare gli Strumenti di Costruzione
# Installare lo strumento moderno di costruzione
pip install build
# Oppure per Poetry
pip install poetry
# Oppure per Hatchling
pip install hatch
Costruire i File di Distribuzione
Utilizzando il pacchetto build (funziona con qualsiasi backend):
# Pulire le costruzioni precedenti
rm -rf dist/ build/ *.egg-info
# Costruire la distribuzione sorgente e la wheel
python -m build
# Questo crea:
# dist/mypackage-0.1.0.tar.gz (distribuzione sorgente)
# dist/mypackage-0.1.0-py3-none-any.whl (wheel)
Utilizzando Poetry:
poetry build
Utilizzando Hatch:
hatch build
Comprendere i Formati di Distribuzione
Distribuzione Sorgente (sdist) - .tar.gz
- Contiene il codice sorgente e le istruzioni di costruzione
- I utenti di pip lo costruiscono durante l’installazione
- Include test, documentazione e altri file per lo sviluppo
Wheel - .whl
- Distribuzione binaria pre-costruita
- Installazione veloce (nessun passo di costruzione)
- Specifica della piattaforma o puramente in Python
- Formato consigliato per la distribuzione
Pubblicare su PyPI
Metodo 1: Caricamento Manuale con Twine (Tradizionale)
# Installare twine
pip install twine
# Controllare il pacchetto prima di caricare
twine check dist/*
# Caricare prima su TestPyPI (consigliato)
twine upload --repository testpypi dist/*
# Testare l'installazione da TestPyPI
pip install --index-url https://test.pypi.org/simple/ mypackage
# Caricare su PyPI produttivo
twine upload dist/*
Configurare le credenziali in ~/.pypirc:
[distutils]
index-servers =
pypi
testpypi
[pypi]
username = __token__
password = pypi-AgEIcHlwaS5vcmc...
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-AgENdGVzdC5weXBpLm9yZw...
Metodo 2: Pubblicazione Trasparente (Consigliato per CI/CD)
La Pubblicazione Trasparente utilizza OpenID Connect (OIDC) per autenticare da piattaforme CI/CD senza conservare i token.
Configurazione su PyPI:
- Vai alle impostazioni del tuo progetto PyPI
- Naviga nella sezione “Pubblicazione”
- Aggiungi un nuovo “publisher in attesa”
- Configura:
- Proprietario: Il tuo username/organizzazione GitHub
- Repository: Nome del repository
- Workflow:
publish.yml - Ambiente:
release(opzionale ma consigliato)
Workflow GitHub Actions (.github/workflows/publish.yml):
name: Publish to PyPI
on:
release:
types: [published]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install build dependencies
run: |
python -m pip install --upgrade pip
pip install build
- name: Build package
run: python -m build
- name: Store distribution packages
uses: actions/upload-artifact@v3
with:
name: python-package-distributions
path: dist/
publish:
needs: build
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- name: Download distributions
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
Vantaggi:
- Nessun token API da gestire o proteggere
- Autenticazione automatica tramite OIDC
- Sicurezza migliorata tramite regole di protezione dell’ambiente
- Tracciamento delle pubblicazioni
Buone Pratiche
1. Gestione delle Versioni
Utilizza la versioning semantica (SemVer): MAJOR.MINOR.PATCH
# Installa lo strumento per incrementare le versioni
pip install bump2version
# Incrementa la versione
bump2version patch # 0.1.0 -> 0.1.1
bump2version minor # 0.1.1 -> 0.2.0
bump2version major # 0.2.0 -> 1.0.0
Configura in .bumpversion.cfg:
[bumpversion]
current_version = 0.1.0
commit = True
tag = True
[bumpversion:file:pyproject.toml]
search = version = "{current_version}"
replace = version = "{new_version}"
[bumpversion:file:src/mypackage/__init__.py]
search = __version__ = "{current_version}"
replace = __version__ = "{new_version}"
2. Includi File Essenziali
README.md: Descrizione chiara del progetto, installazione, esempi di utilizzo LICENSE: Scegli la licenza appropriata (MIT, Apache 2.0, GPL, ecc.) CHANGELOG.md: Documenta le modifiche tra le versioni .gitignore: Escludi artefatti di costruzione, cache, ambienti virtuali
3. Test Completi
# Installa le dipendenze per i test
pip install pytest pytest-cov
# Esegui i test con il coverage
pytest --cov=mypackage tests/
# Genera il report del coverage
pytest --cov=mypackage --cov-report=html tests/
Configura in pyproject.toml:
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "--strict-markers --cov=mypackage"
4. Strumenti per la Qualità del Codice
# Formattazione
black src/ tests/
# Linting
flake8 src/ tests/
# Controllo del tipo
mypy src/
# Ordinamento delle importazioni
isort src/ tests/
Integra nei hook pre-commit (.pre-commit-config.yaml):
repos:
- repo: https://github.com/psf/black
rev: 23.9.1
hooks:
- id: black
- repo: https://github.com/pycqa/flake8
rev: 6.1.0
hooks:
- id: flake8
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.5.1
hooks:
- id: mypy
5. Documentazione
Utilizza Sphinx per la documentazione:
# Installa Sphinx
pip install sphinx sphinx-rtd-theme
# Inizializza la documentazione
cd docs
sphinx-quickstart
# Costruisci la documentazione
make html
O utilizza MkDocs per documentazioni basate su Markdown:
pip install mkdocs mkdocs-material
mkdocs new .
mkdocs serve
6. Integrazione Continua
Testare i pacchetti Python su diverse piattaforme e ambienti è cruciale per la affidabilità. Per ulteriori informazioni sulle prestazioni di Python in diversi scenari di distribuzione, vedi la nostra comparazione di AWS Lambda performance: JavaScript vs Python vs Golang, che esplora come Python si comporta in ambienti serverless.
Flusso di lavoro completo CI/CD (.github/workflows/ci.yml):
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Run tests
run: pytest --cov=mypackage --cov-report=xml
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install black flake8 mypy
- name: Black formatting check
run: black --check src/ tests/
- name: Flake8
run: flake8 src/ tests/
- name: MyPy
run: mypy src/
Problemi Comuni e Soluzioni
Problema 1: Errori di Importazione Dopo l’Installazione
Problema: Il pacchetto è installato ma gli import non funzionano
Soluzione: Assicurati di avere una struttura del pacchetto corretta con i file __init__.py e la configurazione corretta in pyproject.toml:
[tool.setuptools.packages.find]
where = ["src"]
include = ["mypackage*"]
Problema 2: Dipendenze Mancanti
Problema: Il pacchetto è installato ma fallisce all’esecuzione a causa di dipendenze mancanti
Soluzione: Dichiarare tutte le dipendenze necessarie in pyproject.toml:
[project]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
Problema 3: Conflitti di Versione
Problema: Il pacchetto funziona nello sviluppo ma fallisce in produzione
Soluzione: Utilizza ambienti virtuali e specifica le versioni minime:
# Crea un ambiente isolato
python -m venv .venv
source .venv/bin/activate # Su Windows: .venv\Scripts\activate
# Installa in modalità editabile per lo sviluppo
pip install -e ".[dev]"
Problema 4: Dimensione del Pacchetto Grande
Problema: Il pacchetto richiede troppo tempo per il download/installazione
Soluzione: Escludi i file non necessari utilizzando MANIFEST.in:
include README.md
include LICENSE
include pyproject.toml
recursive-include src *.py
recursive-exclude * __pycache__
recursive-exclude * *.py[co]
recursive-exclude tests *
recursive-exclude docs *
Problema 5: Problemi Specifici per la Piattaforma
Problema: Il pacchetto funziona su un OS ma fallisce su un altro
Soluzione: Testa su diverse piattaforme utilizzando i build matrix CI/CD (vedi esempio di CI sopra)
Checklist di Pubblicazione
Prima di pubblicare il tuo pacchetto su PyPI, verifica:
- Tutti i test passano su diverse versioni di Python
- Il codice è formattato e linterizzato
- README.md è completo con esempi
- File LICENSE è incluso
- Il numero di versione è aggiornato
- CHANGELOG.md è aggiornato
- Le dipendenze sono specificate correttamente
- Il pacchetto si costruisce senza errori (
python -m build) - Il pacchetto è testato su TestPyPI
- La documentazione è aggiornata
- Il repository Git è contrassegnato con la versione
- È stato creato un rilascio GitHub (per la pubblicazione trasparente)
Argomenti Avanzati
Entry Points e Strumenti CLI
Creare interfacce della riga di comando:
[project.scripts]
mypackage = "mypackage.cli:main"
Implementazione in src/mypackage/cli.py:
import click
@click.command()
@click.option('--name', default='World', help='Name to greet')
def main(name):
"""Simple CLI tool example"""
click.echo(f'Hello, {name}!')
if __name__ == '__main__':
main()
Per un esempio reale di creazione di pacchetti Python che interagiscono con API esterne, consulta la nostra guida su Integrating Ollama with Python, che dimostra la costruzione di client Python con entrambe le integrazioni API REST e la libreria ufficiale.
Sistemi di Plugin
Abilita la scoperta dei plugin:
[project.entry-points."mypackage.plugins"]
plugin_a = "mypackage_plugin_a:PluginA"
Estensioni C
Per il codice critico per le prestazioni:
[tool.setuptools.ext-modules]
name = "mypackage._speedups"
sources = ["src/mypackage/_speedups.c"]
Pacchetti Namespace
Per i pacchetti distribuiti sotto un namespace comune:
[tool.setuptools.packages.find]
where = ["src"]
include = ["company.*"]
[tool.setuptools.package-data]
"company.mypackage" = ["py.typed"]
Strumenti e Risorse Utili
Strumenti per lo Sviluppo dei Pacchetti
- cookiecutter: Template per progetti Python
- tox: Automazione dei test su diverse versioni di Python
- nox: Automazione flessibile dei test (alternativa a tox)
- pre-commit: Framework per gli hook di Git per la qualità del codice
- commitizen: Standardizza i messaggi di commit e la versioning
Piattaforme di Documentazione
- Read the Docs: Hosting gratuito per la documentazione
- GitHub Pages: Host MkDocs o Sphinx documentazione
- pdoc: Generatore semplice di documentazione API
Registri dei Pacchetti
- PyPI: L’indice Python ufficiale (pypi.org)
- TestPyPI: Ambiente di test (test.pypi.org)
- Anaconda.org: Distribuzione di pacchetti Conda
- GitHub Packages: Hosting di pacchetti privati
Monitoraggio e Analisi
- PyPI Stats: Statistiche di download per i pacchetti
- Libraries.io: Monitoraggio delle dipendenze e allarmi
- Snyk: Scansione delle vulnerabilità di sicurezza
- Dependabot: Aggiornamenti automatici delle dipendenze
Conclusione
Il packaging moderno di Python si è evoluto per essere amichevole per gli sviluppatori con standard come pyproject.toml, potenti backend di costruzione e pubblicazione sicura tramite Pubblicazione Trasparente. Seguendo questa guida, puoi creare pacchetti Python professionali e mantenibili che serviranno efficacemente i tuoi utenti.
Punti chiave:
- Utilizza pyproject.toml per tutti i nuovi progetti
- Scegli il giusto backend di costruzione per le tue esigenze
- Implementa test automatizzati e CI/CD
- Utilizza Pubblicazione Trasparente per una distribuzione sicura senza token
- Segui versioning semantico e mantieni i changelog
- Fornisci documentazione completa e esempi
L’ecosistema del packaging Python continua a migliorare con strumenti migliori, standard e funzionalità di sicurezza. Mantieniti aggiornato con le Proposte di Miglioramento Python (PEPs) e le best practice della comunità per mantenere i tuoi pacchetti moderni e mantenibili.
Link Utili
- Python Packaging User Guide
- PEP 518 - Specificare i Requisiti del Sistema di Costruzione
- PEP 621 - Memorizzare i metadati del progetto in pyproject.toml
- Documentazione di Pubblicazione Trasparente di PyPI
- Documentazione di Setuptools
- Documentazione di Poetry
- Documentazione di Hatch
- TestPyPI
- GitHub del Python Packaging Authority
- Versioning Semantico
- Scegli una Licenza