Py module pour débutants : structure, import et bonnes pratiques

Un module Python est un fichier portant l’extension .py qui regroupe des fonctions, des variables ou des classes. Dès qu’un script dépasse quelques dizaines de lignes, découper le code en modules distincts permet de le réutiliser sans le copier-coller d’un fichier à l’autre. Cette mécanique repose sur le système d’import intégré au langage et sur quelques conventions de nommage qu’il vaut mieux connaître avant d’écrire sa première ligne.

Collision de noms de fichiers : le piège que les tutoriels oublient

Avant même de parler de structure, un réflexe protège des heures de débogage. Python résout les imports en parcourant une liste de chemins stockée dans sys.path. Le répertoire courant figure en première position dans cette liste.

Si vous créez un fichier nommé math.py ou email.py dans votre dossier de travail, Python importera votre fichier au lieu du module standard du même nom. Le programme plante alors avec des erreurs incompréhensibles pour un débutant.

La parade est simple : nommer ses propres modules de façon explicite. Préférer calcul_geometrie.py à math.py, ou service_email.py à email.py. En cas de doute sur un nom déjà pris dans la bibliothèque standard, un appel rapide à import nom_suspect dans un interpréteur vierge suffit à vérifier.

Structure d’un py module : fonctions, variables et garde __name__

Un module ne demande aucune syntaxe particulière. Créez un fichier conversion.py contenant une fonction :

def celsius_vers_fahrenheit(c): return c * 9 / 5 + 32

Ce fichier est déjà un module importable. Toute variable définie au niveau racine du fichier (en dehors d’une fonction) sera elle aussi accessible après import.

Développeur débutant consultant un guide sur les modules Python dans un espace de coworking moderne

Un point technique mérite une attention particulière : le bloc if __name__ == « __main__ ». Quand Python importe un fichier, il exécute tout le code qu’il contient. Si votre module comporte des appels de test écrits directement au niveau racine, ils se déclencheront à chaque import. Placer ces appels dans un bloc conditionnel if __name__ == "__main__": garantit qu’ils ne s’exécutent que lorsque le fichier est lancé directement, jamais lors d’un import.

Organisation recommandée d’un fichier module

  • Les imports du module lui-même figurent en haut du fichier, un par ligne, regroupés par catégorie (bibliothèque standard, paquets tiers, modules locaux).
  • Les constantes et variables de configuration viennent ensuite, en majuscules selon la convention PEP 8.
  • Les définitions de fonctions et de classes occupent le corps du fichier.
  • Le bloc if __name__ == "__main__": ferme le fichier, réservé aux tests rapides ou à un point d’entrée de script.

Import Python : syntaxe et choix entre import et from

Deux formes d’import coexistent. La première, import conversion, charge le module entier. Chaque appel passe alors par le préfixe du module : conversion.celsius_vers_fahrenheit(100). Le code reste explicite sur l’origine de chaque fonction.

La seconde forme, from conversion import celsius_vers_fahrenheit, injecte la fonction directement dans l’espace de noms du script appelant. Plus concis, mais la provenance de la fonction devient invisible si le fichier accumule les imports.

La variante from conversion import * importe tout ce que le module expose. Cette forme est déconseillée dans la majorité des cas : elle pollue l’espace de noms, masque l’origine des fonctions et crée des conflits silencieux entre modules.

Alias et lisibilité

Un alias raccourcit les noms longs sans sacrifier la traçabilité. La syntaxe import numpy as np en est l’exemple classique. Pour vos propres modules, un alias se justifie quand le nom dépasse deux mots ou quand il apparaît des dizaines de fois dans le script.

Packages Python et rôle de __init__.py

Dès qu’un projet dépasse trois ou quatre modules, les regrouper dans un dossier (un package) clarifie l’arborescence. Un package Python est un répertoire contenant un fichier __init__.py.

Le rôle de ce fichier a évolué dans les usages récents. Il ne sert plus seulement à « rendre un dossier importable » : il définit l’API publique du package. En y plaçant des imports sélectifs, vous contrôlez précisément ce qu’un utilisateur obtient en écrivant from mon_package import ma_fonction.

Un __init__.py vide reste valide, mais un fichier pensé comme une interface rend le package plus lisible. La variable __all__, définie dans ce fichier, liste explicitement les noms exportés lors d’un import *.

Deux étudiants débutants apprenant la structure des modules Python ensemble dans une bibliothèque universitaire

Imports absolus ou relatifs dans un package

À l’intérieur d’un package, deux styles coexistent. L’import relatif utilise un point : from .utils import nettoyer. L’import absolu reprend le chemin complet : from mon_package.utils import nettoyer.

Les guides de structure de projet récents privilégient les imports absolus pour les projets exécutables. La raison est pratique : un import relatif dépend du point d’entrée du programme. Si le script est lancé depuis un répertoire inattendu, la résolution échoue. L’import absolu supprime cette ambiguïté.

Bonnes pratiques pour structurer un projet Python

Quelques conventions partagées par la communauté facilitent la maintenance d’un projet à mesure qu’il grandit.

  • Un module fait une seule chose. Si un fichier dépasse quelques centaines de lignes ou mélange des responsabilités distinctes (accès base de données et logique métier, par exemple), le découper en deux modules.
  • Les noms de modules et de packages utilisent des minuscules et des underscores : mon_module.py, jamais MonModule.py. La PEP 8 le spécifie explicitement.
  • Chaque fonction publique porte une docstring décrivant ses paramètres et sa valeur de retour. La PEP 257 encadre le format de ces chaînes de documentation.
  • Les dépendances tierces sont isolées dans un environnement virtuel (venv) pour éviter les conflits entre projets.

Pour diagnostiquer un problème d’import, inspecter sys.path et sys.modules dans l’interpréteur donne immédiatement la liste des chemins parcourus et des modules déjà chargés. C’est le premier réflexe à acquérir avant de chercher plus loin.

Un module bien nommé, un __init__.py qui sert d’interface et des imports absolus couvrent la grande majorité des besoins d’un projet Python débutant. Le reste, publication sur PyPI ou gestion avancée de packages, relève d’une étape ultérieure qui suppose que ces bases sont déjà solides.

Ne manquez rien de l’actu :