Planifions notre voyage
Avant de commencer à coder il faut savoir quoi coder. Nous avons déjà établi notre cible avec un premier schéma mais celui-ci présente une vue macro de la structure de notre projet. Je vous propose de faire un premier dive dans cette dernière.
Qu’est-ce qu’un package ?
Qu’est-ce qui définit concrètement un package en Python ? Est-ce qu’il suffit de créer un dossier et d’y mettre des fichiers .py ?
Pas tout à fait. Un dossier seul ne suffit pas : il faut également un fichier __init__.py à l’intérieur. Mais ce n’est pas tout car en Python le mot package recouvre en réalité deux notions qui se chevauchent et qu’il est important de distinguer.
Le package au sens import est un dossier contenant un fichier __init__.py. Ce fichier, même vide, indique à Python que ce dossier est un module importable. Sans lui vous pouvez avoir tous les .py que vous voulez dans un dossier : Python ne saura pas qu’il peut en importer le contenu. C’est ce qui vous permettra d’écrire from medas_financial_reporting.financial_reporting.data import get_data depuis n’importe où dans votre projet.
Le package au sens distribution est une unité de code empaquetée et installable. C’est ce que vous installez avec pip install ou uv add. Dans ce sens pandas, openpyxl et streamlit sont des packages. Cette configuration se fait dans le fichier pyproject.toml.
Dans notre projet les deux notions se rejoignent : nous allons créer des packages Python structurés et les configurer dans pyproject.toml pour qu’ils soient installables proprement dans notre environnement. C’est justement l’un des avantages du src layout que nous allons adopter par la suite.
Comment décider ce qui constitue un package ?
Il n’y a pas de règle absolue : c’est une question de cohésion. On regroupe dans un même package ce qui a une responsabilité commune et qui a du sens à être utilisé ensemble. Le bon découpage est celui qui rend votre code lisible et maintenable. Gardez ces trois guidelines en mémoire :
Ce qui change ensemble reste ensemble. Si deux modules sont toujours modifiés en même temps c’est qu’ils appartiennent probablement au même package.
Ce qui est réutilisable séparément mérite son propre package. La génération du reporting et l’application
Streamlitont des cycles de vie différents. Nous pourrions très bien remplacerStreamlitparFlask,ReflexouDjangosans toucher au reporting. Nous pourrions même décider que l’interface web sera en JavaScript avecReact. Il faut donc les séparer.La responsabilité unique.
financial_reportinggénère un fichier Excel à partir des données.streamlit_appexpose le reporting à un utilisateur. Si vous n’arrivez pas à résumer la responsabilité d’un package en une phrase c’est peut-être parce qu’il en fait trop.Imaginez l’arborescence du projet en respectant les contraintes suivantes :
src/contenant votre package Python__init__.pytests/à la racinenotebooks/à la racineStructure du projet
Le repo GitHub s’appelle
MEDAS-Financial-Reporting: les tirets sont la convention GitHub. Le package Python s’appellemedas_financial_reporting: le tiret est un opérateur de soustraction en Python et ne peut donc pas faire partie d’un identifiant. On utilise des underscores et des minuscules conformément à la PEP8.Le src layout : pourquoi ce niveau intermédiaire ?
Pourquoi avoir un dossier
medas_financial_reporting/à l’intérieur desrc/alors qu’on a déjà un dossier racineMEDAS-Financial-Reporting/?La réponse vient de la distinction entre les deux notions évoquées plus tôt.
Le dossier racine
MEDAS-Financial-Reporting/est l’enveloppe du dépôt Git : il contient lepyproject.toml, leREADME.md, lesnotebooks/et lestests/. Ce n’est pas du code importable.Le dossier
La Python Packaging Authority 1 décrit le src layout comme le fait de déplacer le code destiné à être importable dans un sous-dossier typiquement nommésrc/medas_financial_reporting/est le package importable, celui que Python chargera quand vous écrirezfrom medas_financial_reporting.financial_reporting.data import get_data.src/, séparé de la racine du projet. Ce séparateur évite un piège classique : sans lui Python trouve votre code directement à la racine et l’importe même s’il n’est pas installé ce qui peut masquer des erreurs de packaging.Solution automatique avec
uvdepuis le templateuvSi vous partez du template proposé, vous pouvez générer le src layout automatiquement avec
uvplutôt que de tout créer à la main.Commencez par supprimer les fichiers de configuration existants puis lancez l’initialisation :
uvva créer le dossiersrc/avec votre package et réécrire unpyproject.tomlcorrectement configuré. Vérifiez ensuite que le dossier généré soussrc/s’appelle bienmedas_financial_reportingavec des underscores. Siuva utilisé des tirets renommez-le :Il ne reste plus qu’à créer les sous-packages et les dossiers manquants :