La modularité
Un programme qui grandit dans un seul fichier devient vite illisible : des centaines de lignes, des fonctions partout, impossible de s'y retrouver. La solution des développeurs professionnels : découper le code en modules, des fichiers séparés qui ont chacun un rôle clair, et qu'on réutilise à volonté.
Dans ce chapitre, on va apprendre à importer des modules tout faits (Python en fournit des centaines), puis à en créer soi-même et à organiser un vrai projet.
Ce qu'on va apprendre
- Comprendre ce qu'est un module Python.
- Importer et utiliser un module existant.
- Créer et réutiliser ses propres fichiers de fonctions.
- Découvrir la structure typique d'un projet Python.
Qu'est-ce qu'un module ?
Définition : Un module est un fichier Python (
.py) contenant du code (fonctions, variables, classes…) qu'on peut importer dans d'autres scripts pour le réutiliser.
Fichier maths_utils.py :
def carre(x):
return x * x
Fichier programme.py :
import maths_utils
print(maths_utils.carre(5)) # 25
main.py, et le navigateur n'a pas de disque où déposer maths_utils.py à côté. Pour essayer ce code, crée les deux fichiers dans le même dossier sur l'ordinateur, puis lance programme.py.Les blocs des sections suivantes, eux, importent des modules de la bibliothèque standard : ceux-là s'exécutent ici même.
Ce qu'un import charge vraiment
Un import n'est pas une déclaration décorative en tête de fichier : c'est une instruction qui s'exécute, et qui range le contenu du module dans un objet portant son nom.
import math ne verse pas le contenu de math dans le programme : il pose sur le bureau une commode nommée math, tiroirs fermés. Pour nous en servir, on ouvre le bon tiroir avec un point : math.sqrt(25).
Regardons ce que la commode contient. dir() liste les noms qu'un module met à disposition.
Le bloc suivant est faux exprès : il oublie d'ouvrir le tiroir.
NameError: name 'sqrt' is not defined. L'import a bien réussi : math existe, mais sqrt n'existe que dedans. Écrire math.sqrt(25) et relance.
Les façons d'importer
Python offre plusieurs syntaxes selon ce dont on a besoin. Ces exemples utilisent des modules standards (déjà installés) : on peut donc les exécuter ici même.
Importer tout le module :
Importer un seul élément :
Renommer avec as :
Importer plusieurs éléments :
from math import *math. devant chaque appel. C'est précisément le problème.On renverse le tiroir sur le bureau sans regarder ce qui en sort. Si on avait une variable nommée
pi, e ou pow, elle est écrasée sans le moindre avertissement. Et à la lecture, plus rien ne dit d'où vient gamma : de ce module, d'un autre, ou du code.Écrire
import math et préfixer, ou from math import sqrt, pi en nommant ce qu'on prend. Le préfixe n'est pas une lourdeur, c'est une information.
Les modules standards les plus utiles
Python est « livré piles incluses » : des centaines de modules prêts à l'emploi.
| Module | Utilisation | Exemple |
|---|---|---|
math | Fonctions mathématiques | math.sqrt(16) |
random | Nombres aléatoires | random.randint(1, 6) |
datetime | Dates et heures | datetime.date.today() |
os | Fichiers, dossiers, système | os.listdir() |
sys | Paramètres du programme | sys.argv |
La liste complète est dans la documentation officielle.
Créer ses propres modules
On peut répartir le code dans plusieurs fichiers pour le rendre plus lisible.
Fichier outils.py :
def saluer(nom):
print(f"Bonjour {nom} !")
def aire_carre(cote):
return cote ** 2
Fichier main.py :
import outils
outils.saluer("Alice")
print("Aire :", outils.aire_carre(5))
random.py dans le dossier sera trouvé avant le vrai module random de Python. Son propre fichier s'importe alors lui-même, et l'erreur qui en découle, du type module 'random' has no attribute 'randint', ne dit pas un mot du vrai coupable.La règle vaut aussi pour
math.py, os.py, json.py, email.py. En cas d'erreur incompréhensible sur un import, regarde d'abord le nom de ses propres fichiers.
Organiser un projet
La règle tient en une phrase : un fichier par rôle, et un point d'entrée unique.
mon_projetmain.pyle programme : il appelle, il n'implémente pasoutils.pyles fonctions réutilisablesmain.py importe outils et enchaîne les appels. outils.py ne sait pas qu'il existe un main.py et ne l'importe jamais : la dépendance va dans un seul sens, sinon les deux fichiers s'importent l'un l'autre et Python s'y perd.
Quand outils.py devient trop gros, on le coupe en plusieurs fichiers rangés dans un dossier, et l'import prend un point de plus : from calculs.statistiques import moyenne. Le parcours Outils de développement traite en détail de la structure d'un projet, des dépendances et des environnements.
__name__ la valeur "__main__". Quand ce même fichier est importé par un autre, __name__ contient son nom de module.
C'est ce qui explique la ligne if name == "main": qu'on croisera dans presque tous les programmes Python. Elle protège le code de démonstration d'un fichier : il s'exécute quand on lance le fichier, et reste silencieux quand on l'importe pour ses fonctions.
Retenons la formule, on n'en aura vraiment besoin que le jour où on écrira un fichier destiné à être importé.
Vérification
1.import math puis import math une seconde fois : que se passe-t-il ?
2.Quelle différence entre import math et from math import sqrt ?
3.Pourquoi éviter from module import * ?
4.À quoi sert le bloc if __name__ == "__main__": ?
À mettre en pratique
Exercice : le lancer de dés. En utilisant le module random, simule le lancer de deux dés à six faces et affiche les deux résultats puis leur somme.
Afficher la solution
random.randint(1, 6) tire un entier entre 1 et 6 inclus. Relance plusieurs fois : le résultat change à chaque exécution.
Synthèse
- Un module est un fichier
.pyréutilisable ; on l'importe avecimport. from module import elementimporte juste ce qu'il nous faut ;asrenomme.- Python fournit de nombreux modules standards (
math,random,datetime…). - Un projet propre = des fichiers aux rôles clairs et un point d'entrée unique (
main.py).