Créer des packages Python : guide du développement jusqu'à PyPI
Maîtrisez l'emballage Python, de la conception au déploiement sur PyPI
Packaging Python a connu des évolutions significatives, avec des outils et des standards modernes qui rendent plus facile que jamais la distribution de votre code.
Ce guide vous accompagne pas à pas dans la création de packages Python professionnels et leur publication sur PyPI. Si vous débutez avec Python ou si vous avez besoin d’un rappel rapide, consultez notre Feuille de rappel Python pour vous familiariser rapidement avec les fondamentaux de Python.

Pourquoi emballer votre code Python ?
L’emballage de votre projet Python offre plusieurs avantages :
- Réutilisabilité : Partagez du code entre plusieurs projets sans copier-coller
- Distribution : Permettez à d’autres d’installer votre code avec un simple
pip install - Gestion des dépendances : Spécifiez clairement et gérez vos dépendances
- Versioning : Suivez les releases et maintenez la compatibilité descendante
- Normes professionnelles : Suivez les meilleures pratiques de la communauté Python
- Documentation : Une structure qui encourage une documentation et des tests adéquats
Structure moderne d’un package Python
Un package bien organisé suit cette structure :
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
Le src-layout est désormais préféré au layout plat car il :
- Empêche les importations accidentelles de code non installé pendant le développement
- Rend les tests plus fiables en forçant l’installation
- Sépare clairement le code source des autres fichiers du projet
Lors de l’organisation de la structure interne de votre package, envisagez d’appliquer les principes d’architecture propre pour rendre votre code plus maintenable et testable. Notre guide sur Les motifs de conception Python pour une architecture propre couvre les principes SOLID, l’injection de dépendances et les motifs d’architecture en couches qui s’intègrent parfaitement aux packages Python.
Le fichier pyproject.toml : configuration moderne
pyproject.toml (PEP 518, 621) est le standard moderne pour la configuration des projets Python, remplaçant le setup.py obsolète :
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "mypackage"
version = "0.1.0"
description = "Un fantastique package Python"
readme = "README.md"
requires-python = ">=3.8"
license = {text = "MIT"}
authors = [
{name = "Votre Nom", email = "vous@example.com"}
]
keywords = ["exemple", "tutoriel", "package"]
classifiers = [
"État de développement :: 4 - Bêta",
"Public cible :: Développeurs",
"Licence :: Approuvée par OSI :: Licence MIT",
"Langage de programmation :: Python :: 3",
"Langage de programmation :: Python :: 3.8",
"Langage de programmation :: Python :: 3.9",
"Langage de programmation :: Python :: 3.10",
"Langage de programmation :: Python :: 3.11",
"Langage de programmation :: 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"]
Sections de configuration clés
- build-system : Spécifie le backend de construction (setuptools, hatchling, poetry-core, flit-core)
- project : Métadonnées et dépendances principales
- project.optional-dependencies : Dépendances supplémentaires (développement, documentation, tests)
- project.scripts : Points d’entrée pour les interfaces en ligne de commande
- tool.* : Configuration spécifique aux outils (black, pytest, mypy, etc.)
Choix d’un backend de construction
Setuptools (Choix standard)
L’option la plus utilisée et compatible :
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.build_meta"
Avantages : Compatibilité universelle, fonctionnalités étendues, écosystème vaste Inconvénients : Configuration plus verbeuse, plus lente que les alternatives modernes
Hatchling (Moderne et rapide)
Backend moderne léger et performant :
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
Avantages : Construction rapide, configuration simple, bonnes valeurs par défaut Inconvénients : Moins de plugins que setuptools
Poetry (Tout-en-un)
Gestion complète des dépendances et de l’environnement :
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
[tool.poetry]
name = "mypackage"
version = "0.1.0"
description = "Un fantastique package Python"
authors = ["Votre Nom <vous@example.com>"]
[tool.poetry.dependencies]
python = "^3.8"
requests = "^2.28.0"
Avantages : Résolution des dépendances, fichiers de verrouillage, workflow intégré Inconvénients : Workflow différent, surface d’outil plus grande
Flit (Minimaliste)
Outil simple pour les packages simples :
[build-system]
requires = ["flit_core >=3.2,<4"]
build-backend = "flit_core.buildapi"
Avantages : Très simple, configuration minimale Inconvénients : Fonctionnalités limitées pour les packages complexes
Construction de votre package
Installer les outils de construction
# Installer l'outil de construction moderne
pip install build
# Ou avec Poetry
pip install poetry
# Ou avec Hatchling
pip install hatch
Construire les fichiers de distribution
Avec le package build (fonctionne avec tout backend) :
# Nettoyer les anciennes constructions
rm -rf dist/ build/ *.egg-info
# Construire la distribution source et le wheel
python -m build
# Cela crée :
# dist/mypackage-0.1.0.tar.gz (distribution source)
# dist/mypackage-0.1.0-py3-none-any.whl (wheel)
Avec Poetry :
poetry build
Avec Hatch :
hatch build
Comprendre les formats de distribution
Distribution source (sdist) - .tar.gz
- Contient le code source et les instructions de construction
- Les utilisateurs de pip le construisent lors de l’installation
- Inclut les tests, la documentation et d’autres fichiers de développement
Wheel - .whl
- Distribution binaire pré-construite
- Installation rapide (aucune étape de construction)
- Spécifique à une plateforme ou pur Python
- Format recommandé pour la distribution
Publication sur PyPI
Méthode 1 : Téléchargement manuel avec Twine (traditionnelle)
# Installer twine
pip install twine
# Vérifier le package avant le déploiement
twine check dist/*
# Télécharger d'abord sur TestPyPI (recommandé)
twine upload --repository testpypi dist/*
# Tester l'installation depuis TestPyPI
pip install --index-url https://test.pypi.org/simple/ mypackage
# Télécharger sur PyPI de production
twine upload dist/*
Configurer les identifiants dans ~/.pypirc :
[distutils]
index-servers =
pypi
testpypi
[pypi]
username = __token__
password = pypi-AgEIcHlwaS5vcmc...
[testpypi]
repository = https://test.pypi.org/legacy/
username = __token__
password = pypi-AgENdGVzdC5weXBpLm9yZw...
Méthode 2 : Publication approuvée (recommandée pour CI/CD)
La publication approuvée utilise OpenID Connect (OIDC) pour s’authentifier depuis les plateformes CI/CD sans stocker de tokens.
Configuration sur PyPI :
- Allez dans les paramètres de votre projet PyPI
- Accédez à la section “Publication”
- Ajoutez un nouveau “éditeur en attente”
- Configurez :
- Propriétaire : Votre nom d’utilisateur GitHub/organisation
- Référentiel : Nom du référentiel
- Workflow :
publish.yml - Environnement :
release(optionnel mais recommandé)
Workflow GitHub Actions (.github/workflows/publish.yml) :
name: Publier sur PyPI
on:
release:
types: [published]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configurer Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Installer les dépendances de construction
run: |
python -m pip install --upgrade pip
pip install build
- name: Construire le package
run: python -m build
- name: Stocker les packages de distribution
uses: actions/upload-artifact@v3
with:
name: distributions-python-package
path: dist/
publish:
needs: build
runs-on: ubuntu-latest
environment: release
permissions:
id-token: write
steps:
- name: Télécharger les distributions
uses: actions/download-artifact@v3
with:
name: distributions-python-package
path: dist/
- name: Publier sur PyPI
uses: pypa/gh-action-pypi-publish@release/v1
Avantages :
- Aucun token API à gérer ou à sécuriser
- Authentification automatique via OIDC
- Sécurité renforcée grâce aux règles de protection de l’environnement
- Historique d’audit de toutes les publications
Bonnes pratiques
1. Gestion des versions
Utilisez la versionning sémantique (SemVer) : MAJOR.MINOR.PATCH
# Installer l'outil de mise à jour de version
pip install bump2version
# Mettre à jour la version
bump2version patch # 0.1.0 -> 0.1.1
bump2version minor # 0.1.1 -> 0.2.0
bump2version major # 0.2.0 -> 1.0.0
Configurez dans .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. Inclure les fichiers essentiels
README.md : Description claire du projet, installation, exemples d’utilisation LICENSE : Choisissez une licence appropriée (MIT, Apache 2.0, GPL, etc.) CHANGELOG.md : Documentez les changements entre les versions .gitignore : Excluez les artefacts de construction, les caches et les environnements virtuels
3. Tests complets
# Installer les dépendances de test
pip install pytest pytest-cov
# Exécuter les tests avec couverture
pytest --cov=mypackage tests/
# Générer le rapport de couverture
pytest --cov=mypackage --cov-report=html tests/
Configurez dans pyproject.toml :
[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_functions = ["test_*"]
addopts = "--strict-markers --cov=mypackage"
4. Outils de qualité du code
# Formatage
black src/ tests/
# Analyse de code
flake8 src/ tests/
# Vérification des types
mypy src/
# Tri des importations
isort src/ tests/
Intégrez dans les hooks pré-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. Documentation
Utilisez Sphinx pour la documentation :
# Installer Sphinx
pip install sphinx sphinx-rtd-theme
# Initialiser la documentation
cd docs
sphinx-quickstart
# Construire la documentation
make html
Ou utilisez MkDocs pour des documents basés sur Markdown :
pip install mkdocs mkdocs-material
mkdocs new .
mkdocs serve
6. Intégration continue
Tester vos packages Python sur différentes plateformes et environnements est crucial pour la fiabilité. Pour des informations sur les performances Python dans différents scénarios de déploiement, consultez notre comparaison de Performances d’AWS Lambda : JavaScript vs Python vs Golang, qui explore comment Python se comporte dans des environnements serverless.
Workflow complet 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: Configurer Python
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Installer les dépendances
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"
- name: Exécuter les tests
run: pytest --cov=mypackage --cov-report=xml
- name: Télécharger la couverture
uses: codecov/codecov-action@v3
with:
file: ./coverage.xml
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configurer Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Installer les dépendances
run: |
pip install black flake8 mypy
- name: Vérification de la formattage Black
run: black --check src/ tests/
- name: Flake8
run: flake8 src/ tests/
- name: MyPy
run: mypy src/
Pièges courants et solutions
Problème 1 : Erreurs d’importation après l’installation
Problème : Le package est installé mais les imports échouent
Solution : Assurez-vous d’une structure de package correcte avec des fichiers __init__.py et une configuration pyproject.toml appropriée :
[tool.setuptools.packages.find]
where = ["src"]
include = ["mypackage*"]
Problème 2 : Dépendances manquantes
Problème : Le package s’installe mais échoue à l’exécution en raison de dépendances manquantes
Solution : Déclarez toutes les dépendances de runtime dans pyproject.toml :
[project]
dependencies = [
"requests>=2.28.0",
"click>=8.1.0",
]
Problème 3 : Conflits de version
Problème : Le package fonctionne en développement mais échoue en production
Solution : Utilisez des environnements virtuels et spécifiez les versions minimales :
# Créer un environnement isolé
python -m venv .venv
source .venv/bin/activate # Sur Windows : .venv\Scripts\activate
# Installer en mode éditable pour le développement
pip install -e ".[dev]"
Problème 4 : Taille de package importante
Problème : Le package prend trop longtemps à télécharger/installer
Solution : Excluez les fichiers inutiles avec 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 *
Problème 5 : Problèmes spécifiques à la plateforme
Problème : Le package fonctionne sur un OS mais échoue sur un autre
Solution : Testez sur plusieurs plateformes à l’aide de builds matriciels CI/CD (voir l’exemple de CI ci-dessus)
Checklist de publication
Avant de publier votre package sur PyPI, vérifiez :
- Tous les tests passent sur les différentes versions de Python
- Le code est formaté et analysé
- README.md est complet avec des exemples
- Le fichier LICENSE est inclus
- Le numéro de version est mis à jour
- CHANGELOG.md est mis à jour
- Les dépendances sont correctement spécifiées
- Le package se construit sans erreurs (
python -m build) - Le package est testé sur TestPyPI
- La documentation est à jour
- Le référentiel Git est tagué avec la version
- Une publication GitHub est créée (pour la publication approuvée)
Sujets avancés
Points d’entrée et outils CLI
Créer des interfaces en ligne de commande :
[project.scripts]
mypackage = "mypackage.cli:main"
Implémentation dans src/mypackage/cli.py :
import click
@click.command()
@click.option('--name', default='Monde', help='Nom à saluer')
def main(name):
"""Exemple d'outil CLI simple"""
click.echo(f'Salut, {name}!')
if __name__ == '__main__':
main()
Pour un exemple concret de création de packages Python qui interagissent avec des API externes, consultez notre guide sur Intégration d’Ollama avec Python, qui démontre la création de clients Python avec l’API REST et l’intégration de bibliothèque officielle.
Systèmes de plugins
Activer la découverte de plugins :
[project.entry-points."mypackage.plugins"]
plugin_a = "mypackage_plugin_a:PluginA"
Extensions C
Pour le code critique de performance :
[tool.setuptools.ext-modules]
name = "mypackage._speedups"
sources = ["src/mypackage/_speedups.c"]
Packages de nommage
Pour les packages distribués sous un même espace de nommage :
[tool.setuptools.packages.find]
where = ["src"]
include = ["entreprise.*"]
[tool.setuptools.package-data]
"entreprise.mypackage" = ["py.typed"]
Outils et ressources utiles
Outils de développement de package
- cookiecutter : Modèles de projet pour les packages Python
- tox : Automatisation des tests sur différentes versions de Python
- nox : Automatisation des tests flexible (alternative à tox)
- pre-commit : Cadre de hooks Git pour la qualité du code
- commitizen : Standardiser les messages de commit et le versionning
Plateformes de documentation
- Read the Docs : Hébergement gratuit de documentation
- GitHub Pages : Hébergement de documentation MkDocs ou Sphinx
- pdoc : Générateur simple de documentation API
Registres de package
- PyPI : L’index officiel des packages Python (pypi.org)
- TestPyPI : Environnement de test (test.pypi.org)
- Anaconda.org : Distribution de packages Conda
- GitHub Packages : Hébergement de packages privés
Surveillance et analyse
- PyPI Stats : Statistiques de téléchargement des packages
- Libraries.io : Surveillance des dépendances et alertes
- Snyk : Analyse des vulnérabilités de sécurité
- Dependabot : Mises à jour automatiques des dépendances
Conclusion
Le packaging Python moderne a évolué pour être plus convivial pour les développeurs grâce à des standards comme pyproject.toml, des backends de construction puissants et une publication sécurisée via la publication approuvée. En suivant ce guide, vous pouvez créer des packages Python professionnels et maintenables qui servent efficacement vos utilisateurs.
Points clés :
- Utilisez pyproject.toml pour tous les nouveaux projets
- Choisissez le bon backend de construction pour vos besoins
- Implémentez des tests automatisés et un CI/CD
- Utilisez la publication approuvée pour un déploiement sécurisé sans token
- Suivez le versionning sémantique et maintenez les journaux de modifications
- Fournissez une documentation complète et des exemples
L’écosystème de packaging Python continue d’améliorer les outils, les standards et les fonctionnalités de sécurité. Restez à jour avec les propositions de renforcement Python (PEPs) et les meilleures pratiques de la communauté pour garder vos packages modernes et maintenables.
Liens utiles
- Guide utilisateur de packaging Python
- PEP 518 - Spécifier les exigences du système de construction
- PEP 621 - Stocker les métadonnées du projet dans pyproject.toml
- Documentation de publication approuvée de PyPI
- Documentation de Setuptools
- Documentation de Poetry
- Documentation de Hatch
- TestPyPI
- GitHub de l’association Python Packaging
- Versionning sémantique
- Choisir une licence