Qualité et passation
- Leçon 18
- 50 min
- Module 6 : Du carnet Jupyter au projet facile à maintenir
Leçon 18 sur 18 · Python pour l'ingénierie de l'IA en pratiqueQualité et passation
1. Bases de l'ordinateur et de l'environnement
2. Valeurs et flux de contrôle
3. Fonctions et structure du programme
4. Fichiers, données et services externes
5. Débogage et fiabilité
6. Du carnet Jupyter au projet facile à maintenir
Ce que vous saurez faire
Confiez ticket-cleaner à une autre personne. Elle reçoit un dossier et suit le README. En cinq minutes, le programme fonctionne et les tests réussissent sur son ordinateur, sans qu’elle vous pose de question. C’est le test à appliquer à chaque projet que vous construirez après ce cours.
Avant de commencerCe qu’il faut savoir et avoir sous la main
Ce que vous devez savoir
- Le fichier de verrouillage et la façon de recréer un environnement, vus dans Isoler les dépendances.
- La commande
python -m ticket_cleaner, vue dans L’interface en ligne de commande.
Ce qu’il vous faut sur votre ordinateur
python -m ticket_cleaner data/tickets.csvfonctionne, etpython -m pytestréussit. Vous avez créé la commande dans L’interface en ligne de commande : exercice guidé et ses tests dans Tester la commande. Si l’un des deux échoue, reprenez ces sections.requirements.txtavec httpx et pytest, créé dans Des tests ciblés : installer pytest, etrequirements-lock.txt, créé dans Isoler les dépendances : noter les versions. Cette leçon recrée le fichier de verrouillage..env.example, créé dans Configuration et secrets : documenter les paramètres.- Les fichiers d’exercice que cette leçon supprime, si vous les avez. Ce sont
first_run.py(Installer et vérifier Python),ticket_values.py(Les valeurs de base),urgent_report.py(Modules et importations),try_mock.py(Utiliser un client HTTP simple),try_token.py(Configuration et secrets) etshow_args.py(L’interface en ligne de commande). - Git est facultatif. Avec Git, le test sur une nouvelle copie utilise
git clone, vu dans L’essentiel de Git et du développement en équipe. - Un terminal dans
~/projects/ticket-cleaner. Vous avez créé le dossier dans Les fichiers et le terminal : exercice guidé. - L’environnement
.venvdu projet, actif dans votre terminal (l’invite commence par(.venv)). Vous l’avez créé dans Isoler les dépendances : exercice guidé. S’il manque ou ne fonctionne plus, supprimez-le et recréez-le à partir du fichier de verrouillage. Suivez Recréer l’environnement à partir de zéro. - Une connexion Internet pour installer ruff (environ 12 Mo).
Testé avec Python 3.14.6, ruff 0.16.10 et pytest 9.1.1 sur macOS, et Python 3.14.4 sur Ubuntu 26.04.
Formatage et analyse du code
Section intitulée « Formatage et analyse du code »On lit le code beaucoup plus souvent qu’on l’écrit. Deux outils facilitent sa lecture et trouvent certains bogues avant son exécution :
- Un formateur réorganise votre code selon un style uniforme : espaces, longueur des lignes, guillemets, lignes vides. Il ne change pas ce que fait le code. Personne ne perd de temps sur la présentation pendant les révisions, et tous les fichiers ont le même style.
- Un analyseur statique lit votre code et signale des structures qui sont souvent des bogues. Par exemple : une importation inutilisée, un nom qui n’existe pas ou une liste comme valeur par défaut.
ruff est un outil qui fait les deux, et il est rapide. Ajoutez-le au projet comme dépendance de développement :
-
Ajoutez
ruff==0.16.10àrequirements.txt. Ajoutez des commentaires pour séparer les besoins du programme des outils nécessaires pour travailler sur le code :requirements.txt # Needed to run the programhttpx==0.28.1# Needed to work on the program: tests, formatting and lintingpytest==9.1.1ruff==0.16.10 -
Installez-le :
python -m pip install -r requirements.txt. -
Créez
pyproject.tomldans le dossier du projet. Les outils Python lisent leurs paramètres dans ce fichier :pyproject.toml # Settings for the development tools. The program itself needs only# requirements-lock.txt.[tool.ruff]line-length = 88[tool.ruff.lint]# The default rules, plus import sorting (I) and common bug patterns (B).extend-select = ["I", "B"][tool.pytest.ini_options]testpaths = ["tests"]testpathsindique à pytest de chercher les tests uniquement danstests/.
Exemple détaillé : ce que ruff trouve
Section intitulée « Exemple détaillé : ce que ruff trouve »Amira crée un fichier avec quelques problèmes courants, ticket_cleaner/messy.py, pour voir ce que fait ruff :
from ticket_cleaner.records import Ticketimport json
def add_problem(problem, problems=[]): problems.append(problem) return problems
def count_open(tickets:list[Ticket])->int: return len( [t for t in tickets if t.status=='open'] )Elle lance l’analyseur statique sur ce fichier :
ruff check ticket_cleaner/messy.pyI001 [*] Import block is un-sorted or un-formatted --> ticket_cleaner/messy.py:1:1
F401 [*] `json` imported but unused --> ticket_cleaner/messy.py:2:8
B006 Do not use mutable data structures for argument defaults --> ticket_cleaner/messy.py:5:35 |5 | def add_problem(problem, problems=[]): | ^^help: Replace with `None`; initialize within function
Found 3 errors.[*] 2 fixable with the `--fix` option (1 hidden fix can be enabled with the `--unsafe-fixes` option).Chaque problème signalé comprend un code, un message et un emplacement (fichier:ligne:colonne). B006 désigne la liste par défaut qui garde les valeurs, vue dans Le contrat d’une fonction. L’analyseur statique la repère sans exécuter le code. Les problèmes marqués [*] peuvent être corrigés automatiquement sans risque :
ruff check --fix ticket_cleaner/messy.pyCette commande supprime l’importation inutilisée et trie les importations. B006 reste, car sa correction change ce que fait la fonction. Une personne doit donc décider. Ensuite, le formateur corrige la présentation :
ruff format ticket_cleaner/messy.pyfrom ticket_cleaner.records import Ticket
def add_problem(problem, problems=[]): problems.append(problem) return problems
def count_open(tickets: list[Ticket]) -> int: return len([t for t in tickets if t.status == "open"])Deux lignes vides entre les fonctions, des espaces autour de :, -> et ==, des guillemets doubles, aucun espace dans les crochets. Le code fait la même chose et ressemble maintenant aux autres fichiers Python. Elle corrige B006 à la main, comme dans le module 3, puis supprime messy.py, car c’était seulement un exemple.
Une structure de projet claire
Section intitulée « Une structure de projet claire »Pendant le cours, vous avez créé des fichiers pour vous exercer : first_run.py, ticket_values.py, urgent_report.py, try_mock.py, try_token.py, show_args.py. Ils ne font pas partie du programme. Une nouvelle personne ne peut pas savoir quels fichiers comptent. Supprimez-les donc, ou déplacez-les dans un dossier hors du projet.
Le projet a alors une structure claire :
ticket-cleaner/├── .env.example the settings, without secret values├── .gitignore├── README.md how to set up, run and work on it├── pyproject.toml settings for ruff and pytest├── requirements.txt what the project uses directly├── requirements-lock.txt the exact version of every package├── data/ sample data├── tests/ one test file for each module└── ticket_cleaner/ the packageCertains fichiers ne doivent pas se trouver dans la copie que vous remettez. L’autre personne les recrée, ou ils sont privés. Inscrivez-les dans .gitignore, que Git et plusieurs autres outils respectent :
.venv/__pycache__/.pytest_cache/.ruff_cache/reports/*.tmp.envMettez à jour .env.example : TICKETS_SOURCE est maintenant l’argument input. Supprimez-le et ajoutez LOG_LEVEL.
Le README
Section intitulée « Le README »Le README est le premier fichier qu’une personne lit. Pour un projet qu’elle doit exécuter, il répond à ces questions, dans cet ordre :
| Section | Réponses |
|---|---|
| Première ligne | Que fait le programme, en une ou deux phrases? |
| Prérequis | Que dois-je avoir avant de commencer? |
| Installation | Quelles commandes exactes dois-je exécuter une seule fois? |
| Exécution | Quelle commande lance le programme, et que vois-je quand il fonctionne? |
| Paramètres et options | Que puis-je changer? |
| Codes de sortie | Comment un script qui lance le programme connaît-il le résultat? |
| Travailler sur le code | Comment lancer les tests et les vérifications? |
Écrivez les commandes exactement comme une personne les tape. Montrez la sortie attendue pour qu’elle sache que chaque étape a fonctionné. Ce sont les mêmes règles que pour une leçon. Voici le début du README d’Amira. Le fichier complet comprend chaque section du tableau :
# ticket-cleaner
Checks support-ticket records from a CSV file, a JSON file or a web service, and writes a summary report. Every record that is not valid is listed in the report, with the reason.
## Requirements
- Python 3.12 or newer. Check with `python3 --version` (`python --version` on Windows).- No account. The `remote` input downloads a public file.
## Set up
Do these steps once, in a terminal in this folder.
1. Make a virtual environment: `python3 -m venv .venv`. On Windows, type `python` instead of `python3`.2. Activate it. On macOS and Linux: `source .venv/bin/activate`. On Windows (PowerShell): `.venv\Scripts\Activate.ps1`. The prompt now starts with `(.venv)`.3. Install the exact versions of the dependencies: `python -m pip install -r requirements-lock.txt`
## Run
```shpython -m ticket_cleaner data/tickets.csv```
Expected output (the last lines):
```text15 rows: 9 valid, 6 rejected.Report: reports/summary.json```Exercice guidé : préparer la passation
Section intitulée « Exercice guidé : préparer la passation »-
Ajoutez ruff et
pyproject.tomlcomme ci-dessus. -
Lancez les vérifications sur tout le projet :
Fenêtre de terminal ruff check .ruff format .Corrigez ce que
ruff checksignale. Relancez les deux commandes jusqu’à ce queruff check .afficheAll checks passed!(toutes les vérifications ont réussi).ruff format .doit indiquer qu’aucun fichier n’est à modifier. -
Relancez les tests :
python -m pytest. Le formateur ne doit pas avoir changé ce que fait le code, et les tests le prouvent. -
Supprimez les fichiers d’exercice. Créez
.gitignoreet mettez à jour.env.example. -
Recréez le fichier de verrouillage dans un nouvel environnement. Il contiendra seulement les paquets de
requirements.txt(voir l’erreur courante ci-dessous) :Fenêtre de terminal deactivaterm -rf .venvpython3 -m venv .venvsource .venv/bin/activatepython -m pip install -r requirements.txtpython -m pip freeze > requirements-lock.txtFenêtre de terminal deactivateRemove-Item -Recurse -Force .venvpython -m venv .venv.venv\Scripts\Activate.ps1python -m pip install -r requirements.txtpython -m pip freeze > requirements-lock.txtFenêtre de terminal deactivaterm -rf .venvpython3 -m venv .venvsource .venv/bin/activatepython -m pip install -r requirements.txtpython -m pip freeze > requirements-lock.txtLe fichier de verrouillage contient 13 lignes :
httpx,pytest,ruffet les paquets dont ils ont besoin. -
Écrivez
README.mdavec chaque section du tableau.
Prouvez-le : une nouvelle copie
Section intitulée « Prouvez-le : une nouvelle copie »Vous ne pouvez pas tester un README sur l’ordinateur où vous l’avez écrit. Votre environnement, vos variables et votre mémoire comblent toutes les lacunes. Testez-le comme une nouvelle personne le découvre : une nouvelle copie, un nouveau terminal et seulement le README.
-
Ouvrez un nouveau terminal. N’activez rien.
-
Faites une copie du projet sans les fichiers indiqués dans
.gitignore. Si vous utilisez Git et avez enregistré votre travail dans un commit (enregistrement des modifications), clonez-le :Fenêtre de terminal cd ~/projectsgit clone ticket-cleaner ticket-cleaner-freshSans Git, copiez le dossier
ticket-cleanerdans votre gestionnaire de fichiers et nommez la copieticket-cleaner-fresh. Supprimez.venv,reportset tous les dossiers__pycache__dans la copie. -
Exécutez
cd ticket-cleaner-fresh, ouvrezREADME.mdet faites exactement ce qu’il indique, rien de plus. N’utilisez aucune commande de mémoire. -
Chaque fois que vous devez faire quelque chose que le README n’indique pas, arrêtez. Ajoutez l’étape manquante au README du projet original.
-
Quand le README est complet, supprimez
ticket-cleaner-freshet recommencez. Continuez jusqu’à ce qu’une nouvelle copie fonctionne avec seulement le README. Le programme affiche15 rows: 9 valid, 6 rejected.(15 lignes : 9 valides, 6 rejetées). Les commandespython -m pytestetruff check .réussissent.
À vous de jouer : une révision de la passation
Section intitulée « À vous de jouer : une révision de la passation »Demandez à une personne qui ne connaît pas le projet de faire le test sur une nouvelle copie. Elle doit utiliser son propre ordinateur, si possible avec un système d’exploitation différent. Ne l’aidez pas. Notez chaque endroit où elle s’arrête ou pose une question.
Si personne n’est disponible, faites-le sur un autre ordinateur. Ou attendez un jour et refaites-le vous-même. Une lacune que vous avez manquée aujourd’hui sera plus facile à voir demain.
Afficher les questions les plus fréquentes
- « Quel Python? » → La section Prérequis doit donner la version et la commande pour la vérifier.
- « L’invite n’affiche pas (.venv). » → La section Installation doit donner la commande d’activation pour chaque système. Elle doit aussi inclure la correction de la stratégie d’exécution PowerShell vue dans Isoler les dépendances.
- « Où est le rapport? » → La section Exécution doit donner le chemin du fichier de sortie et la sortie attendue.
- « Une ligne WARNING indique-t-elle un problème? » → La section Exécution doit préciser ceci : chaque enregistrement rejeté produit un
WARNING(avertissement), et c’est normal. - « Comment lancer les tests? » → La section Travailler sur le code.
Erreur courante
Un fichier de verrouillage avec des paquets que le projet n'utilise pas
Symptôme : requirements-lock.txt contient beaucoup plus de lignes que prévu, par exemple ipykernel, jupyter_client, traitlets et vingt autres. Ou une nouvelle installation prend beaucoup de temps ou échoue sur un autre système.
Cause : pip freeze liste tous les paquets de l’environnement, pas seulement ceux de requirements.txt. Vous avez peut-être installé quelque chose pour l’essayer. Par exemple, ipykernel pour un carnet (notebook) Jupyter dans De la rigueur dans le carnet. Il se retrouve maintenant dans le fichier de verrouillage, et chaque nouvelle personne l’installe aussi.
Correction :
- Créez le fichier de verrouillage dans un nouvel environnement, avec seulement
requirements.txtinstallé (étape 5 de l’exercice guidé). - Comparez l’ancien et le nouveau fichier de verrouillage. Chaque ligne doit correspondre à un paquet de
requirements.txtou à une de ses dépendances. - Installez les outils personnels, comme
ipykernel, hors de l’environnement du projet. Ou réinstallez-les après avoir créé le fichier de verrouillage.
Vérifiez votre compréhension
ruff check --fix a supprimé une importation et trié les autres. Comment savoir qu'il n'a rien brisé?
Afficher la réponse
Lancez les tests : python -m pytest. Le formatage et les corrections sans risque ne changent pas ce que fait le code. Mais les tests le prouvent, plutôt que de simplement le croire. C’est pourquoi le README demande de lancer les trois opérations : tests, formatage et vérification.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Vérification du module : que signifie exécuter le projet dans un nouvel environnement avec seulement le README, et comment le démontrer?
Afficher la réponse
C’est une copie sans .venv, sans reports et sans aucun paramètre provenant de votre terminal. Vous l’installez en suivant le README étape par étape, sans aucune étape faite de mémoire. Vous le démontrez avec les résultats de cette exécution : le programme affiche 15 rows: 9 valid, 6 rejected.. Les commandes python -m pytest et ruff check . réussissent, toutes dans la nouvelle copie. Chaque lacune trouvée est maintenant une étape dans le README.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Récapitulatif
- Un formateur uniformise la présentation. Un analyseur statique repère des structures qui sont souvent des bogues. ruff fait les deux :
ruff format .etruff check .. - Après toute modification automatique, lancez les tests.
- Une structure claire contient seulement les fichiers nécessaires au projet.
.gitignoreliste ce qui reste privé ou sera recréé. - Le README décrit le programme, les prérequis, l’installation, l’exécution et ce que vous voyez quand tout fonctionne.
- Créez le fichier de verrouillage dans un nouvel environnement. Testez le README sur une nouvelle copie et ajoutez chaque étape manquante.
Vous pouvez maintenant construire, tester et confier un projet Python à une autre personne. Le travail final réunit tous ces éléments.
Leçon suivante : Travail final