Skip to content

Modules Python

Les modules sont un moyen fondamental d’organiser le code Python. Ils vous permettent de regrouper des fonctions, des classes et des variables connexes dans des fichiers séparés, favorisant la réutilisabilité, la maintenabilité et la structure logique du code. Un module est essentiellement un fichier Python (.py) contenant des définitions et des instructions Python.

Considérez les modules comme des boîtes à outils. Au lieu d’avoir tous vos outils éparpillés partout, vous regroupez les outils connexes (comme des clés ou des tournevis) dans des boîtes spécifiques. Lorsque vous avez besoin d’un outil particulier, vous prenez la bonne boîte à outils (importez le module) et choisissez ensuite l’outil dont vous avez besoin.

Créons un module nommé helpers.py :

helpers.py
"""Un module simple avec des fonctions d'aide."""
PI = 3.14159
def greet(name):
"""Salue la personne avec le nom donné."""
print(f"Hello, {name}!")
class Calculator:
"""Une classe de calculatrice de base."""
def add(self, x, y):
return x + y

Pour utiliser les définitions d’un module dans un autre fichier Python (par exemple, main.py), vous utilisez l’instruction import. La syntaxe de base est :

import module_name
# Ou importer plusieurs modules
import module1, module2
# Ou style préféré (une importation par ligne)
import module_one
import module_two

Lorsque Python rencontre import helpers, il recherche helpers.py (ou d’autres types de modules) dans son chemin de recherche. Une fois trouvé, il exécute le code du module (s’il n’a pas déjà été importé) et rend ses définitions disponibles via le préfixe du nom du module.

Exemple (main.py dans le même répertoire que helpers.py) :

main.py
import helpers
helpers.greet("Alice")
print(f"La valeur de PI est approximativement : {helpers.PI}")
calc = helpers.Calculator()
result = calc.add(5, 3)
print(f"5 + 3 = {result}")

L’exécution de python main.py produit :

Hello, Alice!
The value of PI is approximately: 3.14159
5 + 3 = 8

Un module est chargé et exécuté une seule fois, la première fois qu’il est importé lors de l’exécution d’un programme. Les importations ultérieures du même module récupèrent simplement l’objet module déjà chargé.

Cette instruction vous permet d’importer des noms spécifiques (fonctions, classes, variables) directement dans l’espace de noms du script actuel, évitant ainsi la nécessité du préfixe du module.

from module_name import name1
# Ou importer plusieurs noms
from module_name import name1, name2
# Ou importer et renommer
from module_name import name1 as alias_name

Exemple :

main_from.py
from helpers import greet, PI
from helpers import Calculator as Calc # Renommage
greet("Bob")
print(f"PI: {PI}")
my_calc = Calc()
print(f"10 + 5 = {my_calc.add(10, 5)}")

Ceci évite de préfixer avec helpers. mais introduit les noms importés directement dans la portée actuelle. Soyez conscient des potentielles collisions de noms.

Vous pouvez importer tous les noms publics (ceux ne commençant pas par un underscore _) d’un module en utilisant :

from module_name import *

Attention : Cette pratique est généralement déconseillée dans le code de production. Elle importe potentiellement de nombreux noms dans l’espace de noms actuel, ce qui rend incertaine l’origine d’un nom spécifique et augmente le risque de conflits de noms. Elle est acceptable dans les sessions interactives ou parfois dans des schémas de modules spécifiques (__init__.py).

Lorsque vous importez my_module, Python le recherche dans cet ordre :

  • Le répertoire contenant le script d’entrée (ou le répertoire actuel si en mode interactif).
  • Les répertoires listés dans la variable d’environnement PYTHONPATH (si définie). Le format dépend de la plateforme (par exemple, séparés par des deux-points sur Unix/macOS, par des points-virgules sur Windows).
  • Chemins par défaut dépendants de l’installation (généralement dans le répertoire site-packages de l’installation Python).

Le chemin de recherche est accessible par programme via sys.path, qui est une liste de chaînes de caractères.

import sys
print(sys.path)

PYTHONPATH est une variable d’environnement que vous pouvez définir pour ajouter des répertoires supplémentaires où Python recherchera des modules. Sa syntaxe reflète celle de la variable PATH du système.

Exemple (Linux/macOS) :

Terminal window
export PYTHONPATH="/home/user/my_python_libs:/another/path"

Exemple (Invite de commandes Windows) :

Terminal window
set PYTHONPATH=C:\Users\user\my_python_libs;D:\other_path

Bien que PYTHONPATH puisse être utile, la gestion des dépendances avec des environnements virtuels et l’installation standard de paquets (pip) est l’approche moderne préférée.

Un espace de noms est un mappage des noms vers les objets (comme un dictionnaire). Python utilise les espaces de noms pour éviter les collisions de noms.

Python suit la règle LEGB pour la résolution de portée : Local -> Locales de la fonction englobante -> Global -> Intégré.

Pour modifier une variable globale depuis l’intérieur d’une fonction, vous devez utiliser le mot-clé global. Pour modifier une variable dans la portée d’une fonction englobante (dans des fonctions imbriquées), utilisez le mot-clé nonlocal (Python 3+).

x = 100 # Global
def outer_func():
y = 20 # Local englobant
def inner_func():
nonlocal y # Modifie la variable de portée englobante
global x # Déclare l'intention de modifier la variable globale
z = 5 # Local
y += 5
x += 1
print(f"Intérieur : x={x}, y={y}, z={z}")
inner_func()
print(f"Extérieur : x={x}, y={y}")
outer_func()
print(f"Global : x={x}")

La fonction intégrée dir(), lorsqu’elle est appelée sans arguments, retourne une liste de noms dans la portée locale actuelle. Lorsqu’elle est appelée avec un objet (comme un module) en tant qu’argument, elle retourne une liste triée de noms définis par cet objet (ses attributs, méthodes, etc.).

import math
print(dir(math)) # Liste les noms dans le module math
my_var = 10
def my_func(): pass
print(dir()) # Liste les noms dans la portée actuelle (globale)

La sortie peut inclure des noms spéciaux comme __name__ (nom du module) et __file__ (chemin du fichier du module).

Ces fonctions intégrées retournent des dictionnaires représentant respectivement les espaces de noms global et local.

Rechargement de modules (importlib.reload)

Section titled “Rechargement de modules (importlib.reload)”

Les modules sont généralement chargés une seule fois. Si vous modifiez le fichier source d’un module pendant l’exécution de votre programme principal (courant lors du développement interactif ou des applications à long terme), les modifications ne seront pas automatiquement prises en compte. Pour forcer le rechargement d’un module déjà importé, utilisez la fonction importlib.reload() (note : reload était une fonction intégrée en Python 2, mais a été déplacée vers importlib en Python 3).

import importlib
import helpers
# ... code utilisant helpers ...
# Supposons que helpers.py a été modifié
importlib.reload(helpers)
# Utilisez maintenant la version mise à jour de helpers
helpers.greet("Utilisateur mis à jour")

Utilisez reload avec prudence, car cela peut entraîner des incohérences si ce n’est pas géré attentivement, surtout avec des dépendances complexes ou des objets à état.

Les paquets offrent un moyen de structurer l’espace de noms des modules de Python en utilisant des « noms de modules à points ». Un paquet est essentiellement un répertoire contenant des modules Python et potentiellement d’autres sous-paquets. Pour être reconnu comme un paquet régulier (avant Python 3.3, et toujours une pratique courante), le répertoire doit contenir un fichier nommé __init__.py (qui peut être vide).

Exemple de structure :

sound/
__init__.py
formats/
__init__.py
wavread.py
aiffread.py
...
effects/
__init__.py
echo.py
surround.py
...
filters/
__init__.py
equalizer.py
...

Vous pouvez importer des modules à partir de paquets en utilisant la notation pointée :

import sound.effects.echo
sound.effects.echo.apply_echo(...)
from sound.formats import wavread
wavread.read_wavfile(...)
from sound.filters.equalizer import Equalizer
eq = Equalizer()

Le fichier __init__.py sert à plusieurs fins :

Exemple (sound/effects/__init__.py) :

sound/effects/__init__.py
print("Initialisation du paquet d'effets sonores...")
# Rend echo et surround disponibles directement via 'from sound.effects import ...'
from . import echo
from . import surround
# Contrôle 'from sound.effects import *'
__all__ = ["echo", "surround"]

Avec ce __init__.py, vous pourriez faire :

import sound.effects
sound.effects.echo.apply_echo(...) # Accès via sous-module

Note : Python 3.3 a introduit les paquets d’espace de noms implicites (Implicit Namespace Packages, PEP 420), qui permettent de créer des paquets sans fichier __init__.py, principalement utiles pour diviser un seul grand paquet entre plusieurs répertoires.