Un collègue ouvre votre notebook, voit un chiffre et vous demande de le recalculer. C’est à ce moment que commence la transmission. Les sorties enregistrées peuvent encore s’afficher alors que le fichier de données a changé, qu’un paramètre n’existe plus dans les cellules ou que le calcul utilisait un autre environnement Python.
Un fichier Jupyter .ipynb conserve du code et des sorties. Ces deux éléments peuvent être enregistrés ensemble sans que les sorties aient été recalculées après la dernière modification du code. C’est une propriété du format des notebooks, pas une preuve que l’analyse est fausse. Elle oblige simplement à distinguer un résultat visible d’un résultat que l’on sait reproduire.
Voici une méthode pour livrer une analyse à un autre analyste : un dossier autonome, un calcul lancé dans un noyau neuf et un résultat attendu vérifié. L’atelier ci-dessous a été exécuté sur macOS avec Python 3.14.7, dans un environnement recréé à partir du ZIP. Les données sont entièrement fictives.

Pourquoi « j’ai exécuté toutes les cellules » ne suffit pas toujours
Le noyau est le processus qui exécute le code du notebook et garde ses variables en mémoire. Pendant l’exploration, vous pouvez lancer une cellule, changer une valeur, supprimer la cellule qui l’avait créée, puis continuer à calculer. La variable peut encore exister dans cette session. Votre collègue, lui, repart de zéro.
L’ordre visible des cellules ne raconte donc pas nécessairement l’ordre de leur exécution. Et même un redémarrage réussi ne règle pas tout : le CSV lu aujourd’hui peut être différent de celui utilisé hier. Il faut fixer à la fois le calcul, ses entrées et son environnement.
Dans cet atelier, NBClient lance réellement les cellules du notebook. Il ne remplace pas leur contenu par un script qui recalculerait le même chiffre ailleurs. La documentation Jupyter décrit cette exécution, le choix du noyau, du répertoire de travail et l’arrêt à la première erreur. Exécuter un notebook avec NBClient.
Le cas : 1 000 euros de ventes nettes sur septembre
L’analyste doit transmettre le montant net des commandes livrées, datées de septembre 2026. Le fichier contient huit commandes. Les montants sont stockés en centimes entiers, pour ne pas introduire d’arrondis flottants dans cet exemple.
Le périmètre est précis : date de commande à partir du 1er septembre inclus et avant le 1er octobre, statut livree. On soustrait les remboursements présents dans le fichier aux montants bruts des commandes retenues. Ce choix décrit les commandes de septembre avec les remboursements du snapshot ; il ne prétend pas calculer un chiffre d’affaires comptable selon la date de remboursement.
| Commande |
Pourquoi la garder ou l’écarter |
Montant net retenu |
| C001 |
Livrée, commande du 2 septembre |
100 € |
| C002 |
Livrée, commande du 5 septembre, remboursement de 50 € |
200 € |
| C003 |
Annulée |
Écartée |
| C004 |
Livrée, commande du 21 septembre, remboursement de 100 € |
300 € |
| C005 |
Livrée, commande du 30 septembre |
200 € |
| C006 |
Datée du 1er octobre |
Écartée |
| C007 |
Datée du 31 août |
Écartée |
| C008 |
Livrée, commande du 25 septembre |
200 € |
Le contrôle manuel donne cinq commandes, 1 150 € bruts, 150 € remboursés, soit 1 000 € nets. Ce petit tableau est essentiel : il établit la référence avant de demander au programme de la retrouver. Copier sa propre sortie dans un fichier « attendu » ne constituerait pas ce contrôle indépendant.
Ce que contient le dossier à transmettre
Télécharger l’atelier Jupyter et ses données fictives.
Le dossier atelier-notebook sépare les responsabilités :
| Fichier |
Ce qu’il permet de reprendre |
analyse.ipynb |
Le raisonnement, le chargement des données et le calcul |
commandes.csv |
Les huit lignes utilisées |
parametres.json |
Les bornes de dates et les statuts retenus |
donnees.sha256 |
L’empreinte du CSV attendu |
attendu.json |
Les paramètres et les montants à retrouver |
requirements-macos-py314.txt |
Les versions des paquets de l’environnement testé |
rejouer.py et README.md |
La commande de reprise, les contrôles et leurs limites |
L’empreinte SHA-256 est une signature calculée à partir du contenu du fichier. Elle détecte ici un CSV modifié, même si son nom reste identique. Elle ne prouve ni l’origine ni la qualité des données.
Les paramètres restent lisibles hors du notebook :
{
"debut_inclus": "2026-09-01",
"fin_exclue": "2026-10-01",
"statuts": ["livree"]
}
Une personne qui reprend le dossier peut ainsi répondre à « quel mois ? » et « quelles commandes ? » sans chercher une valeur dispersée entre plusieurs cellules.
Rejouer le notebook dans un dossier neuf
Pour suivre exactement l’essai réalisé, utilisez macOS avec Python 3.14 installé, un terminal et une connexion Internet pour télécharger les dépendances. La version testée est 3.14.7. Aucun compte Jupyter ni abonnement n’est nécessaire. Le calcul lui-même utilise ensuite seulement les fichiers locaux. Les commandes et la liste de paquets fournis n’ont pas été validés sur Windows ou Linux.
Décompressez le ZIP. Ouvrez le terminal dans le dossier atelier-notebook, puis lancez :
python3.14 -m venv .venv
.venv/bin/python -m pip install -r requirements-macos-py314.txt
.venv/bin/python rejouer.py
La première commande crée un environnement Python séparé. La deuxième y installe les versions enregistrées. La troisième exécute le notebook avec ce même Python. Le script choisit explicitement cet interpréteur pour éviter qu’un noyau Jupyter déjà installé sur la machine ne lance un autre environnement. Le lien entre un nom de noyau et sa commande de lancement est décrit dans la documentation Jupyter sur les noyaux.
À la fin, vous devez lire :
OK : 5 commandes ; brut 1150 EUR ; remboursements 150 EUR ; net 1000 EUR
Deux fichiers apparaissent dans sorties : analyse-executee.ipynb, avec les cellules et leurs sorties recalculées, et resultat.json, avec les montants et les paramètres utilisés. Vous pouvez inspecter le notebook dans votre lecteur Jupyter habituel ; aucun serveur Jupyter n’est nécessaire pour la commande ci-dessus.
Le script supprime ses sorties précédentes avant de démarrer, vérifie le CSV, vide les sorties du notebook en mémoire, puis ouvre un noyau neuf. Il exécute les cellules dans leur ordre et compare le JSON obtenu à la référence. Les chemins sont rattachés au dossier de l’atelier, pas au répertoire depuis lequel vous avez ouvert le terminal.
Pour transmettre l’environnement, gardez la liste de versions et les instructions, puis recréez .venv. Copier ce répertoire vers une autre machine n’est pas la méthode retenue : les environnements virtuels contiennent notamment des chemins vers leur interpréteur et sont conçus pour être recréés. Documentation Python sur les environnements virtuels.
Vérifier que le contrôle sait aussi refuser
Un résultat vert est plus instructif lorsque l’on a vu le contrôle détecter un changement pertinent. Faites les deux essais suivants dans deux copies distinctes du dossier original.
Premier essai : changer une donnée. Dans commandes.csv, remplacez les 10000 centimes de C001 par 11000, puis relancez. Le script doit s’arrêter avant le calcul avec commandes.csv diffère du snapshot attendu. Il signale que vous n’êtes plus en train de reproduire la même analyse.
Deuxième essai : changer le périmètre. Dans l’autre copie, ajoutez annulee à la liste statuts de parametres.json. Le calcul inclut alors C003 : six commandes et 1 900 € nets. Le notebook peut parfaitement s’exécuter, mais la comparaison doit échouer avec résultat ou paramètres différents de attendu.json.
Ces deux échecs ont été observés pendant la préparation de l’atelier. Une troisième vérification a retiré la cellule qui charge les données : l’exécution dans un noyau neuf a échoué sur une variable absente (NameError). Le dossier original a ensuite été relancé avec succès. Cela montre ce que contrôlent les mécanismes livrés ; cela ne constitue pas une validation de tous les notebooks ni de tous les environnements.
Si le nouveau périmètre est volontaire, il faut expliquer la modification, revoir le calcul manuel et versionner ensemble les nouveaux paramètres et le nouvel attendu. Remplacer automatiquement attendu.json par la dernière sortie ferait disparaître précisément le signal que l’on cherche à conserver.
Une analyse reproductible peut encore être mal définie
Retrouver deux fois 1 000 € ne démontre pas que la définition convient au directeur financier. Peut-être attend-il les factures émises, les remboursements datés du mois ou un montant hors taxes. Ces questions appartiennent à la définition de l’indicateur. Le dossier doit conserver cette définition à côté du calcul. L’article sur les modèles sémantiques et les indicateurs développe ce point.
La méthode devient plus exigeante avec des données réelles. Pour une table distante, il faut conserver un extrait autorisé ou identifier une version effectivement accessible au lecteur. Une date écrite dans le README ne remonte pas automatiquement une base dans le temps. Pour un traitement aléatoire ou dépendant d’un service externe, il faut aussi définir ce que l’on attend : égalité exacte, tolérance chiffrée ou ensemble de propriétés à respecter.
Les versions figées réduisent une source de variation, mais ne garantissent ni la disponibilité future des paquets ni un comportement identique sur tous les systèmes. L’atelier établit une reprise sur l’environnement déclaré, pas une promesse universelle.
Avant de livrer votre prochaine analyse, faites reprendre le dossier par une personne qui n’a pas votre session ouverte. Elle doit pouvoir retrouver le périmètre, lancer le calcul et expliquer pourquoi le résultat est accepté ou refusé. C’est ce passage de relais qui transforme une exploration personnelle en analyse réutilisable.