Cours de Python / Créer des modules et réutiliser du code avec import
Un module est une unité de code Python réutilisable, souvent un simple fichier .py. L’instruction import recherche et initialise un module ; elle ne se contente pas de copier son texte, ce qui rend importants l’emplacement des fichiers et les instructions exécutées au niveau supérieur.
Séparer le calcul du programme appelant
Placez la fonction de calcul dans expense_math.py et le code qui l’utilise dans app.py. Les deux fichiers de cet exercice doivent se trouver dans le même dossier. Le module porte le nom expense_math sans l’extension dans l’import. Utilisez un tiret bas plutôt qu’un trait d’union pour les noms de modules importés avec cette syntaxe.
import expense_math lie le nom du module ; la fonction devient accessible par expense_math.total. La variante from expense_math import total lie directement le nom total, ce qui exige de surveiller les collisions avec d’autres noms. Elle n’évite pas l’initialisation du module. Les règles officielles des modules Python détaillent ces formes d’import.
Évitez de nommer vos fichiers json.py ou csv.py : dans un chemin de recherche prioritaire, ils peuvent masquer les modules de la bibliothèque standard. Choisissez un nom décrivant votre propre logique, plutôt qu’un nom déjà utilisé par une dépendance.
Créer les deux fichiers complets et les exécuter
Python 3 suffit ; aucun paquet tiers ne doit être installé. Créez un dossier d’exercice, puis enregistrez les deux fichiers suivants en UTF-8. Dans ce dossier, expense_math.py contient exactement :
def total(amounts):
return sum(amounts)
Le fichier app.py, à côté du précédent, contient exactement :
import expense_math
print(expense_math.total([3500, 8000, 2500]))
Ouvrez le terminal dans ce dossier, avec l’environnement virtuel du projet activé, puis exécutez :
python app.py
Sur macOS ou Ubuntu hors environnement virtuel, utilisez python3 app.py si votre interpréteur se nomme python3. Le programme doit afficher une ligne contenant 14000, somme de 3500, 8000 et 2500. La fonction est définie dans le module, tandis que l’affichage est décidé par le programme appelant, selon la distinction entre return et print.
Comprendre la recherche et l’initialisation
Avec l’exécution directe d’un fichier comme python app.py, le dossier du script fait normalement partie des chemins où Python recherche ses modules. Dans une session interactive ou avec un autre mode d’exécution, le contexte peut être différent. Le dossier de travail ne constitue donc pas à lui seul toute la règle de recherche.
Si une ModuleNotFoundError survient, vérifiez le nom expense_math, l’extension réelle du fichier, la présence des deux fichiers côte à côte et l’interpréteur choisi par votre terminal ou éditeur. Un fichier enregistré comme expense_math.py.txt ne convient pas. Vérifiez aussi que vous lancez bien le bon app.py. Évitez de modifier arbitrairement sys.path ou de copier le module dans le dossier global d’installation pour contourner une mauvaise disposition du projet.
Le schéma générique suivant illustre le même principe avec d’autres noms :
practice/
main.py
helper.py
Dans ce schéma, main.py importerait helper.py. Il ne s’agit pas de fichiers supplémentaires à créer pour l’exercice : conservez les noms réels app.py et expense_math.py indiqués ci-dessus.
Les instructions au niveau supérieur du module s’exécutent lors de sa première initialisation par import dans le processus. Une définition de fonction crée la fonction ; son corps attend un appel. À l’inverse, un print(), un input() ou une opération sur des données placés directement au niveau supérieur peuvent démarrer dès l’import. Réservez donc les opérations effectives à des fonctions puis appelez-les depuis un point d’entrée explicite.
Un module déjà chargé est normalement conservé dans sys.modules. Répéter le même import ne réexécute pas son code de niveau supérieur dans ce cas. Pour vérifier une modification simple pendant cet apprentissage, relancez le script dans un nouveau processus ; dans un interpréteur déjà ouvert, un nouvel import ne suffit pas nécessairement à charger le texte modifié.
Tester la réutilisation et éviter les cycles
- Dans app.py uniquement, remplacez 3500 par 4500. Sans modifier la fonction de calcul, relancez le programme : il doit afficher 15000. Restaurez ensuite 3500.
- Ajoutez temporairement
print("module loaded")au début d’expense_math.py, sans indentation. Au prochain lancement d’app.py, cette ligne apparaît avant 14000. Elle démontre l’initialisation du module ; retirez-la pour retrouver l’affichage initial. - Avec ce print de test encore présent, une variante d’app.py contenant deux fois
import expense_mathn’affiche le message qu’une fois pendant ce lancement normal. Restaurez ensuite les deux fichiers d’origine et vérifiez la seule ligne 14000.
Un import circulaire peut poser problème si deux modules s’importent mutuellement et demandent un nom avant que son module ait fini de l’initialiser. Tous les cycles ne déclenchent pas systématiquement une erreur, mais ils rendent cet ordre plus difficile à comprendre. Déplacez la logique commune dans un troisième module ou organisez une dépendance à sens unique, au lieu d’ajouter des imports au hasard pour masquer le symptôme.




