← Partie 2 : Environnements virtuels | Partie 1 : Syntaxe Python | Retour aux tutoriels
Objectif: transformer un script en package Python réutilisable, versionnable et publiable proprement.
Fonctionnement: exécute les commandes dans l'ordre, contrôle les "Sortie attendue", puis applique le défi final.
Ton dossier contient un utilitaire de validation d'emails. Tu veux l'importer dans 3 APIs différentes. Le packaging évite les copier-coller.
email-tools/
├── pyproject.toml
├── README.md
├── LICENSE
├── src/
│ └── email_tools/
│ ├── __init__.py
│ └── validator.py
└── tests/
└── test_validator.py
[build-system]
requires = ["setuptools>=70", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "email-tools-cf"
version = "0.1.0"
description = "Outils de validation d'emails"
readme = "README.md"
requires-python = ">=3.10"
authors = [
{name = "Coder Facile", email = "contact@example.com"}
]
dependencies = [
"email-validator>=2.2.0,<3.0"
]
[project.optional-dependencies]
dev = [
"pytest>=8.0,<9.0",
"ruff>=0.8,<1.0"
]
[tool.setuptools.packages.find]
where = ["src"]
# src/email_tools/validator.py
from email_validator import validate_email, EmailNotValidError
def is_valid(email: str) -> bool:
try:
validate_email(email, check_deliverability=False)
return True
except EmailNotValidError:
return False
# Dans l'environnement virtuel actif py -m pip install --upgrade pip build py -m build
Sortie attendue: un dossier dist/ est créé avec un fichier .whl et un .tar.gz.
Erreur fréquente: erreur de métadonnées pyproject.toml. Solution: vérifier name, version, et la section build-system.
Résultat attendu dans dist/:
dist/ ├── email_tools_cf-0.1.0-py3-none-any.whl └── email_tools_cf-0.1.0.tar.gz
# Nouveau venv de test
py -m venv .venv-test
.\.venv-test\Scripts\Activate.ps1
py -m pip install dist\email_tools_cf-0.1.0-py3-none-any.whl
# Test rapide
py -c "from email_tools.validator import is_valid; print(is_valid('a@b.com'))"
Sortie attendue: l'import fonctionne et la commande affiche True.
Erreur fréquente: ModuleNotFoundError après installation. Solution: vérifier que le package contient bien le dossier src/email_tools avec __init__.py.
py -m pip install twine
Sortie attendue: twine est installé dans l'environnement actif.
py -m twine check dist/*
Sortie attendue: message "PASSED" pour tous les artefacts.
Erreur fréquente: README mal formaté. Solution: corriger README.md puis régénérer le build.
py -m twine upload --repository testpypi dist/*
Sortie attendue: upload réussi et URL de package sur TestPyPI.
Erreur fréquente: 403 Forbidden. Solution: vérifier le token TestPyPI et les droits associés.
py -m twine upload dist/*
Sortie attendue: package visible sur PyPI avec la version publiée.
Erreur fréquente: "File already exists". Solution: incrémenter la version dans pyproject.toml puis rebuild.
En entreprise, on publie souvent sur un registre privé (Nexus, Artifactory, Azure Artifacts, GitLab Package Registry).
[distutils]
index-servers =
interne
[interne]
repository = https://packages.example.com/repository/pypi-internal/
username = __token__
password = pypi-XXXXXXXXXXXXXXXXXXXXXXXX
py -m twine upload --repository interne dist/*
Sortie attendue: artefacts disponibles dans le registry interne de l'entreprise.
Erreur fréquente: erreur TLS/certificat. Solution: vérifier certificats de l'infra et l'URL exacte du registre.
# 1) Monter version dans pyproject.toml # version = "0.2.0" # 2) Commit + tag git git add . git commit -m "release: v0.2.0" git tag v0.2.0 # 3) Build + checks + upload py -m build py -m twine check dist/* py -m twine upload dist/*
Sortie attendue: tag git créé, artefacts rebuildés, publication acceptée pour la nouvelle version.
Erreur fréquente: tag déjà existant. Solution: choisir une nouvelle version sémantique et recréer le cycle de release.
Tu vas transformer un script local en package installable.
mkdir labo-package cd labo-package py -m venv .venv .\.venv\Scripts\Activate.ps1 py -m pip install --upgrade pip build twine
Sortie attendue: environnement de travail prêt avec build et twine disponibles.
# pyproject.toml [build-system] requires = ["setuptools>=70", "wheel"] build-backend = "setuptools.build_meta" [project] name = "hello-cf-tool" version = "0.1.0" description = "Mini outil exemple" requires-python = ">=3.10" [tool.setuptools.packages.find] where = ["src"]
# src/hello_cf_tool/main.py
def hello(name: str) -> str:
return f"Bonjour {name}, package OK"
# src/hello_cf_tool/__init__.py
from .main import hello
py -m build
py -m pip install dist\hello_cf_tool-0.1.0-py3-none-any.whl
py -c "from hello_cf_tool import hello; print(hello('Equipe'))"
Sortie attendue: la commande Python affiche "Bonjour Equipe, package OK".
Erreur fréquente: nom du wheel introuvable. Solution: vérifier le nom réel dans dist/ et adapter la commande d'installation.
Tu sais maintenant structurer un package Python, le builder, le tester et le publier proprement.
Mission: industrialiser ton package avec une vraie chaîne de release.
Partie 1 : Syntaxe Python | ← Revenir à la Partie 2 | Retour aux tutoriels