Pendant des années, les développeurs Python se sont appuyés sur un écosystème fragmenté d'outils de packaging, jonglant souvent entre setup.py, setup.cfg et divers backends de build. Ce manque de standardisation a engendré confusion et dette technique. Cependant, avec l'adoption des PEP 517 et 518, le paysage s'est stabilisé. Aujourd'hui, le packaging Python est défini par le fichier pyproject.toml, un format de configuration standardisé qui simplifie à la fois la construction et la distribution des packages.
Ce guide explore les meilleures pratiques modernes pour créer, tester et distribuer des packages Python, s'adressant aux développeurs qui souhaitent s'assurer que leurs bibliothèques sont robustes, reproductibles et faciles à installer pour la communauté.
La configuration centrale : pyproject.toml
Le workflow moderne de packaging Python tourne entièrement autour du fichier pyproject.toml. Cette source unique de vérité remplace la nécessité de multiples fichiers de configuration. Il définit le système de build et les métadonnées du projet, garantissant que tout outil respectant la PEP 517 peut construire votre projet de manière cohérente.
Un pyproject.toml typique pour un projet moderne ressemble à ceci :
[build-system]
requires = ["setuptools>=61.0", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "my-awesome-library"
version = "0.1.0"
description = "A sample library demonstrating modern Python packaging"
readme = "README.md"
license = {text = "MIT"}
authors = [
{name = "Jane Doe", email = "jane@example.com"}
]
requires-python = ">=3.8"
dependencies = [
"requests>=2.28.0",
"click>=8.0"
]
[project.optional-dependencies]
dev = [
"pytest>=7.0",
"black"
]
[project.urls]
Homepage = "https://github.com/janedoe/my-awesome-library"
Documentation = "https://my-awesome-library.readthedocs.io"
Notez l'utilisation de métadonnées statiques dans la section [project]. Contrairement aux métadonnées dynamiques dans setup.py, les métadonnées statiques permettent un parsing plus rapide par des outils comme PyPI et assurent la reproductibilité sur différents environnements. Les dépendances sont strictement versionnées pour éviter les changements cassants dans les bibliothèques amont.
Construction et distribution des artefacts
Une fois votre configuration en place, l'étape suivante consiste à générer les artefacts de distribution. La norme industrielle a évolué des distributions sources (.tar.gz) et des wheels hérités (.egg) vers les wheels modernes (.whl). Les wheels modernes incluent des binaires préconstruits et des métadonnées, accélérant considérablement les temps d'installation pour les utilisateurs finaux.
Pour construire votre projet, utilisez le package build, qui est l'outil recommandé pour créer des distributions sources et des wheels. Tout d'abord, installez l'outil de build :
python -m pip install build
Ensuite, exécutez la commande de build :
python -m build
Cette commande crée un répertoire dist/ contenant à la fois la distribution source (sdist) et le wheel. La sdist inclut tous les fichiers source et permet aux utilisateurs de construire le package à partir du code source sur leurs systèmes, tandis que le wheel fournit un format rapide et installable pour la plupart des utilisateurs.
Téléversement sur PyPI
Vos artefacts étant prêts, l'étape finale est la distribution. La fonctionnalité de publication de confiance (Trusted publishing) introduite dans la version 4.0+ de twine simplifie le processus de téléversement en supprimant le besoin de jetons API à longue durée de vie. Au lieu de cela, il utilise OIDC (OpenID Connect) pour l'authentification, ce qui est plus sécurisé et pratique pour les pipelines CI/CD.
Installez twine :
python -m pip install twine
Téléversez vos distributions :
python -m twine upload dist/*
Toujours tester vos téléversements sur TestPyPI en premier pour détecter les erreurs avant de toucher au dépôt principal. Vous pouvez le faire en spécifiant le drapeau --repository testpypi et en configurant votre .pypirc ou en utilisant des variables d'environnement pour les identifiants.
Meilleures pratiques pour la maintenance à long terme
Le packaging n'est pas une tâche unique. Pour maintenir un projet en bonne santé, considérez les pratiques suivantes :
- Gestion des versions : Utilisez le versionnement sémantique (SemVer) pour communiquer les changements cassants.
- Épinglage des dépendances : Épinez les dépendances dans votre
pyproject.tomlpour garantir des builds cohérents, mais utilisez des plages flexibles (par ex.,>=2.0) pour permettre les correctifs de sécurité. - Intégration CI/CD : Automatisez les tests et la publication en utilisant GitHub Actions ou GitLab CI pour s'assurer que chaque version est testée sur plusieurs versions de Python.
- Documentation : Gardez votre
README.mdet votre documentation à jour, car ce sont les premières choses que les utilisateurs voient sur PyPI.
Conclusion
Le packaging Python est devenu un processus robuste et standardisé. En tirant parti de pyproject.toml, des outils de build modernes et de méthodes de distribution sécurisées, les développeurs peuvent se concentrer sur l'écriture de code plutôt que sur le dépannage des problèmes d'installation. Adopter ces pratiques modernes garantit que vos contributions à l'écosystème Python sont accessibles, fiables et maintenables pour les années à venir.