Retour à la leçon·Leçon 2 sur 8·Un environnement qui tiendra
Un projet qu'une autre personne peut ouvrir
Le même diaporama que les téléchargements, rendu sous forme de page. Lancez le diaporama pour le présenter en plein écran — les flèches ou un clic avancent d'une diapositive, Échap quitte.
Ce que couvre cette leçon
- La forme d'un projet
- data/raw est en lecture seule
- Des chemins qui fonctionnent sur la machine d'un autre
- Les sorties sont jetables, et c'est le test
- Ce qui entre dans le contrôle de version
- Notebooks et scripts font des métiers différents
- Un README réellement lu
- Ce qui vient ensuite
Notes du présentateur
Où vivent les données brutes, le code et les sorties, pourquoi un chemin en dur garantit que le script ne tourne que sur une machine, et la règle qui rend une analyse rejouable — ne jamais écrire dans le dossier que l'on lit.La forme d'un projet — Exemple
muac-analysis/ data/ raw/ l'export tel qu'il est arrive, jamais modifie interim/ fichiers intermediaires, supprimables sans risque outputs/ tables/ figures/ scripts/ read_register.py indicator_table.py notebooks/ exploration.ipynb pyproject.toml uv.lock README.md .gitignoreNotes du présentateur
Presque toute analyse de ce secteur comporte les quatre mêmes sortes de fichiers, et donner à chacune un emplacement fixe supprime une catégorie de questions que personne ne devrait avoir à poser. La ligne importante est la première.data/raw est en lecture seule — Exemple
data/raw/muac-screening-artibonite-2024.v1.csv data/raw/muac-screening-artibonite-2024.v2.csvNotes du présentateur
L'export tel qu'il est arrivé est la seule chose du projet que vous ne pouvez pas reproduire. Tout le reste — le tableau nettoyé, les figures, les tableaux d'indicateurs — peut être régénéré en réexécutant le code. Le fichier brut, non : le serveur d'où il vient aura changé. Il n'est donc jamais modifié, jamais écrasé, jamais trié dans Excel « juste pour regarder ». Si une correction arrive, elle se pose à côté de l'original sous un nouveau nom plutôt que de le remplacer. Ce nommage mérite d'être délibéré :data/raw est en lecture seule — Exemple
data/raw/muac_final.csv data/raw/muac_final_v2.csv data/raw/muac_FINAL_corrige(1).csvNotes du présentateur
et non Une analyse exécutée sur la v1 doit continuer à se reproduire sur la v1. Si le nom de fichier est écrasé, le chiffre du trimestre dernier ne pourra plus jamais être expliqué — et expliquer le chiffre du trimestre dernier fait partie de ce qu'on vous demandera.Des chemins qui fonctionnent sur la machine d'un autre — En Python
# S'execute sur exactement un ordinateur. muac = pd.read_csv("C:/Users/marie/Bureau/muac-screening-artibonite-2024.v1.csv")Notes du présentateur
C'est la raison la plus fréquente pour laquelle le script d'un collègue échoue sur votre portable :Des chemins qui fonctionnent sur la machine d'un autre — En Python
from pathlib import Path import pandas as pd # __file__ est ce script ; son parent est scripts/, dont le parent est le projet. PROJECT = Path(__file__).resolve().parent.parent RAW = PROJECT / "data" / "raw" OUTPUTS = PROJECT / "outputs" muac = pd.read_csv(RAW / "muac-screening-artibonite-2024.v1.csv")Notes du présentateur
Le correctif consiste à écrire des chemins relatifs au projet, et à laisser Python déterminer où se trouve le projet.Des chemins qui fonctionnent sur la machine d'un autre
- Il s'exécute depuis n'importe où.
python scripts/indicator_table.pyet `python… - Il fonctionne sous Windows.
Pathassemble avec/dans votre source et produit\sous Windows. Ne construisez… - Il est repérable. Chaque fichier touché par le script se trouve sous
RAWouOUTPUTS: un lecteur voit les…
Notes du présentateur
Trois avantages : Dans un notebook,__file__n'existe pas. Définissez plutôt la racine du projet explicitement dans la première cellule, et gardez le reste du notebook relatif à elle :- Il s'exécute depuis n'importe où.
Des chemins qui fonctionnent sur la machine d'un autre — En Python
from pathlib import Path PROJECT = Path.cwd().parent # le notebook vit dans notebooks/ assert (PROJECT / "data" / "raw").exists(), f"pas la racine du projet : {PROJECT}"Notes du présentateur
L'assertion compte plus qu'il n'y paraît. Sans elle, un notebook lancé depuis le mauvais répertoire échoue plusieurs cellules plus loin, sur une erreur déroutante concernant une colonne absente.Les sorties sont jetables, et c'est le test — Shell
rm -rf outputs/ uv run python scripts/indicator_table.py git status # ne doit rien afficher d'inattenduNotes du présentateur
Si supprimeroutputs/puis réexécuter les scripts ne le restaure pas à l'identique, quelque chose dans l'analyse n'est pas reproductible — une étape manuelle, une modification faite dans Excel, une cellule exécutée dans le désordre.Les sorties sont jetables, et c'est le test — En Python
OUTPUTS = PROJECT / "outputs" / "tables" OUTPUTS.mkdir(parents=True, exist_ok=True) indicator_table.to_csv(OUTPUTS / "gam_by_commune.csv", index=False)Notes du présentateur
Prenez-en l'habitude avant toute transmission. C'est la vérification la moins coûteuse qui soit et elle attrape la défaillance la plus difficile à diagnostiquer plus tard. Créez les répertoires de sortie depuis le code plutôt que d'attendre qu'ils existent :parents=Truecrée les répertoires intermédiaires ;exist_ok=Truefait qu'une seconde exécution n'échoue pas. Un collègue qui clone le projet obtient les dossiers sans qu'on le lui dise.Ce qui entre dans le contrôle de version
À versionner À ne pas versionner scripts/,notebooks/data/raw/— voir ci-dessouspyproject.toml,uv.lockdata/interim/README.mdoutputs/.gitignore.venv/,__pycache__/Ce qui entre dans le contrôle de version — Exemple
.venv/ __pycache__/ *.pyc data/raw/ data/interim/ outputs/ .ipynb_checkpoints/Ce qui entre dans le contrôle de version
- Ne versionnez jamais de données brutes de bénéficiaires — identifiées ou pseudonymisées
Notes du présentateur
Ne versionnez jamais de données brutes de bénéficiaires, identifiées ou pseudonymisées. Git conserve chaque version de chaque fichier pour toujours ; un fichier supprimé dans un commit ultérieur reste dans l'historique, et un dépôt interne le lundi peut être partagé le vendredi. Si les données sont synthétiques ou déjà publiques, les versionner est un confort. Sinon, le répertoire brut reste dehors et le README indique d'où vient le fichier. Les identifiants de connexion suivent la même règle, en plus strict : un jeton DHIS2, une clé d'API KoboToolbox ou un mot de passe de base de données n'apparaissent jamais dans un script, un notebook ou un commit.Ce qui entre dans le contrôle de version — En Python
import os # Lu depuis l'environnement ; la valeur n'entre jamais dans le depot. token = os.environ["DHIS2_TOKEN"]Notes du présentateur
Gardez la valeur dans un fichier.envcouvert par.gitignore, et documentez le nom de la variable — non sa valeur — dans le README.Notebooks et scripts font des métiers différents — En Python
# scripts/read_register.py from pathlib import Path import pandas as pd def read_register(path: Path) -> pd.DataFrame: return pd.read_csv( path, dtype={"child_id": "string", "commune": "string"}, na_values={"muac_mm": ["-99"]}, )Notes du présentateur
Les deux ont leur place dans un projet et ne sont pas interchangeables. Un notebook sert à regarder : explorer un nouvel export, vérifier une distribution, produire une figure à coller dans un rapport. Il s'exécute dans le désordre, porte un état invisible et se compare mal en diff, ce qui en fait un mauvais endroit pour ce qui doit s'exécuter à l'identique au trimestre prochain. Un script sert à produire : il s'exécute de haut en bas, prend des arguments, et réussit ou échoue. Quand une exploration devient un chiffre que quelqu'un va rapporter, déplacez-la dans un script. Le flux de travail pratique consiste à explorer dansnotebooks/, puis à déplacer la partie stabilisée dansscripts/et à la réimporter :Notebooks et scripts font des métiers différents — En Python
# Dans le notebook import sys sys.path.append(str(PROJECT / "scripts")) from read_register import read_register muac = read_register(RAW / "muac-screening-artibonite-2024.v1.csv")Notes du présentateur
Le notebook et le script lisent désormais le fichier de la même façon, et il n'y a qu'un seul endroit à corriger quand la sentinelle change.Un README réellement lu — Exemple
# Tableaux d'indicateurs du depistage PB Produit les taux de MAG et de MAS par commune a partir du registre de depistage de l'Artibonite. ## Executer uv sync uv run python scripts/indicator_table.py \ --input data/raw/muac-screening-artibonite-2024.v1.csv \ --output outputs/tables ## Donnees data/raw n'est pas versionne. Telechargez le registre depuis le partage du programme et placez-le la sous son nom de fichier versionne.Notes du présentateur
Deux commandes et trois phrases valent mieux qu'une page que personne ne termine :Ce qui vient ensuite
- Le projet a une forme et les chemins survivent à un changement de machine.
Notes du présentateur
Le projet a une forme et les chemins survivent à un changement de machine. L'unité suivante fait entrer les données : lire un CSV, un classeur Excel et un export à largeur fixe sans perdre un zéro initial ni se tromper de date.