HOWTO · Python

Structure de projet pour une application Python

Apprenez à structurer une application Python

Sur cette page

Un projet Python facile à maintenir garde une racine épurée, regroupe le code associé dans des packages et n’ajoute des dossiers de support que lorsque l’application en a besoin. Choisissez l’organisation en fonction du mode d’exécution du programme : une application modulaire peut tout de même être déployée sous la forme d’un petit monolithe.

Choisir une organisation adaptée à votre application

Une organisation claire facilite la recherche et la maintenance du code, ainsi que le partage du travail avec des collaborateurs. Elle n’impose pas de découper le programme en microservices. Une petite application peut rester un programme unique à déployer, tout en regroupant le code associé en modules et en packages. Ajoutez des répertoires lorsqu’ils définissent une séparation utile pour le projet ; évitez les dossiers vides créés uniquement pour imiter la structure d’un projet plus vaste.

L’organisation adéquate dépend du fonctionnement de l’application et de son contenu. Un outil en ligne de commande peut n’avoir besoin que du code de l’application, des informations sur ses dépendances et de tests. Une application Web peut aussi nécessiter des modèles et des ressources statiques. Un projet utilisant SQLite peut créer un fichier de base de données local, tandis qu’un projet connecté à un service de base de données conserve généralement ces données hors de l’arborescence source.

Commencer par la racine du projet

La racine du projet est le répertoire qui contient les fichiers utilisés pour développer, tester, documenter et empaqueter l’application. Parmi les choix courants figurent un README.md contenant les instructions d’installation et d’utilisation, une LICENSE précisant comment d’autres personnes peuvent utiliser et distribuer le code, ainsi qu’une déclaration de dépendances telle que pyproject.toml ou requirements.txt. Ces fichiers ont des rôles différents ; un projet n’a pas besoin de tous les formats d’empaquetage ou de déclaration des dépendances.

Les applications Python n’ont pas de nom de fichier de point d’entrée imposé. Un programme en ligne de commande peut être lancé avec python -m package_name, tandis qu’un framework ou une configuration d’empaquetage peut définir une autre commande. Choisissez le mode de lancement adapté à l’application au lieu de supposer que chaque projet a besoin de run.py ou de setup.py.

Créez un environnement virtuel local pour isoler les packages installés pour le projet. Ne le placez pas sous contrôle de version ; les collaborateurs peuvent créer le leur à partir des informations sur les dépendances. Un fichier .gitignore exclut généralement cet environnement, ainsi que les caches et autres fichiers générés. La racine peut rester épurée : ajoutez de la documentation ou une configuration d’empaquetage selon les besoins du projet.

Organiser le code de l’application en packages

Regroupez les modules Python par responsabilité. Par exemple, un blog peut placer le code lié aux comptes dans users et celui lié aux articles dans posts. Il s’agit d’une organisation ordinaire au sein d’un même processus : les deux packages peuvent fonctionner comme des parties d’une seule application et n’ont pas besoin de communiquer en tant que services indépendants.

Un package classique contient souvent un fichier __init__.py. Celui-ci peut être vide ou exposer certains noms dans l’interface du package. Python prend aussi en charge les packages d’espace de noms, qui peuvent se passer de ce fichier. Suivez donc le style de package et les outils choisis pour le projet au lieu de considérer __init__.py comme indispensable dans tous les cas. Placez le code partagé dans un module ou un package lorsque plusieurs parties l’utilisent, et évitez de dupliquer le même comportement dans différents dossiers.

Ajouter des tests, de la documentation et des ressources Web au besoin

Un répertoire tests sépare les vérifications automatisées du code de l’application. Les tests sont utiles même dans les petits projets : ils facilitent la vérification du comportement attendu au fil des modifications du code. Un répertoire docs peut accueillir des instructions plus détaillées pour les utilisateurs ou les contributeurs lorsque le README ne suffit plus.

Les projets Web ont souvent un répertoire templates pour le HTML rendu par l’application et un répertoire static pour des ressources telles que les fichiers CSS, JavaScript et les images. Leur emplacement exact dépend du framework et de sa configuration. Une application en ligne de commande qui n’est pas une application Web n’a généralement aucune raison de les inclure.

Les modèles de base de données peuvent être placés là où ils s’intègrent le mieux à l’architecture choisie ; un projet peut utiliser un module dédié tel que models.py ou un package regroupant plusieurs catégories de modèles. Un fichier comme database.db n’est pertinent que si l’application utilise réellement une base de données locale sous forme de fichier, par exemple SQLite. N’ajoutez pas de fichier de base de données à l’arborescence source simplement parce que l’application stocke des données ailleurs.

Exemple : une petite application de blog

Ce blog regroupe le code des comptes et des articles dans des packages distincts, et place à la racine les ressources propres au Web ainsi que les fichiers de support du projet. L’arborescence est un point de départ : les conventions du framework peuvent placer les modèles, les fichiers statiques ou les modèles HTML ailleurs. Le fichier de base de données est présent pour une configuration SQLite locale ; l’environnement virtuel local est volontairement exclu de l’arborescence suivie par le contrôle de version.

Exécutez cet exemple :

Le code et les libellés ou sorties affichés dans cette section restent en anglais.

layout = [
    "blog/",
    "├── README.md",
    "├── LICENSE",
    "├── pyproject.toml",
    "├── blog/",
    "│   ├── __init__.py",
    "│   ├── users/",
    "│   └── posts/",
    "├── templates/",
    "├── static/",
    "├── tests/",
    "└── database.db  (local SQLite only)",
]
print("\n".join(layout))
blog/
├── README.md
├── LICENSE
├── pyproject.toml
├── blog/
│   ├── __init__.py
│   ├── users/
│   └── posts/
├── templates/
├── static/
├── tests/
└── database.db  (local SQLite only)

L’exemple ne détaille ni la configuration du déploiement ni les spécificités du framework ; adaptez-le donc à votre chaîne d’outils. Ajoutez des fichiers comme models.py dans le package responsable du traitement des données, ou développez un package à mesure qu’il prend de l’ampleur. Dans un projet en ligne de commande, omettez les dossiers Web ; avec un service de base de données, omettez le fichier de base de données local. Gardez le même principe à mesure que le projet évolue : chaque répertoire doit aider à repérer le code ou les ressources associés.