Une page de Le Lab de la taverne

Python : le fichier __main__.py

Par Darko Stankovski, 02/06/2022 (Mise à jour 07/04/2026) — Débutant

Tout développeur Python connait le nom spécial __main__ utilisé dans la structure if __name__ == "__main__":.

Ce nom spécial __main__ est le nom que l’interpréteur attribue au script ou module principal, le module que vous exécutez lorsque vous exécutez un programme Python.

Mais savez-vous que ce nom peut aussi être utilisé pour nommer un fichier : __main__.py ?

Dans quel cas faut-il l’utiliser ? C’est ce que nous allons voir dans cet article.

Rappel sur la structure d’un projet

Question récurrente de tout projet informatique… En Python il n’y a pas de spécification officielle (pas de PEP) qui décrit comment structurer un projet. Il y a cependant une recommandation proposée par Kenneth Reitz en 2013 et qui est toujours d’actualité. Kenneth Reitz a repris le post précédent dans son livre The Hitchhiker’s Guide to Python, que je vous conseille de bookmarquer si pas encore fait.

Cette structure est depuis largement adoptée par la communauté et je ne vais pas la reprendre ici mais me concentrer sur l'arborescence du code.

Ainsi, un projet simple qui tient en un seul script ne contiendra à sa racine que ce script. C’est la structure de notre projet d’application de lancer de dés.

Un projet plus important, décomposé en modules, doit avoir pour racine un package qui définira le namespace racine du projet. Lorsque vous concevez un projet d’envergure, vous avez alors votre script à la racine de ce package.

Mais se pose alors un problème : comment faire évoluer le code lorsque vous passez d’un simple script à un projet plus complexe ? Car il y a déjà une habitude sur la manière de lancer votre programme. Dans notre cas, c’était par python -m diceroller. Dites vous que des scripts de lancement peuvent contenir ce type d’appel et nous souhaitons éviter d’avoir à les modifier.

Le fichier __main__.py

Le fichier __main__.py fournit à un package une interface en ligne de commande. C'est ce que dit la doc.

Ainsi, en faisant évoluer notre projet de lancer de dés d’un script à une arborescence de packages, nous allons nommer le package racine du même nom que notre script, diceroller, et nous transférerons tout le code que contenait notre script dans le fichier __main__.py à la racine de notre arborescence de packages.

Vous pouvez donc exécuter le projet exactement comme précédemment, python -m diceroller.

Utilisation idiomatique

L’objectif ce fichier __main__.py est de fournir un point d’entrée à votre programme, point d’entrée similaire à un script. Ce fichier doit rester court et fait appel aux ressources organisés dans des modules.

Bien que ce soit possible, il ne contient pas la structure idiomatique if name == '__main__': mais fait directement appel aux fonctions dans d’autres modules.

En adaptant notre projet, le fichier __main__.py dans le package diceroller contient :

from .cli import interaction_loop

interaction_loop()

La fonction interaction_loop() est donc déplacée dans un module cli dans le package racine. Les deux autres fonctions sont également déplacées dans des modules adaptés.

La structure générale du projet devient celle de l’illustration ci-contre.

Note sur l’import

La PEP 8 recommande que les imports soient absolus. De même, il est conseillé d’importer un namespace, c’est à dire un module qui permettrait d’identifier où est déclaré la fonction.

Mais dans le cas présent, nous sommes dans un fichier court qui servira, dans une approche plus complexe, au routage de l’appel. Cela fait donc parti, à mon sens, des cas où les appels relatifs ont leur sens.

Une structure stable et évolutive

Ce qui m’intéresse dans ce type de composant, c’est la possibilité de faire évoluer un projet tout en le maintenant stable dans le sens où l’évolution du code ne nécessite aucune adaptation de la production. Nous pouvons ainsi, à partir d’un script, faire évoluer notre projet vers une structure plus complexe sans modifier l’usage que nous avions jusqu’ici.

Nous allons maintenant pouvoir réutiliser les fonctions définies pour cette application en les important de manière cohérente.

En conclusion

L’usage de fichier __main__.py était assez rare en Python mais je commence à le voir de plus en plus souvent. C’est le point d’entrée parfait d’un programme Python qui lève toute ambiguïté, qui évite de se poser la question « quel module est le module principal ? ». Pensez-y lors de vos créations de projets.

Comme d’habitude, le code source est disponible sur mon GitHub.

Licence Creative Commons

Licence Creative Commons Attribution - Pas d'Utilisation Commerciale - Pas de Modification 4.0 International