L'instruction import en Python : utiliser un module

L'instruction import rend utilisable dans un fichier du code écrit ailleurs : bibliothèque standard, paquet installé ou autre fichier de votre projet.
5 min de lecture
Believemy logo

Définition

Au début, un programme tient dans un seul fichier. Puis il grossit, une fonction utile mériterait de servir ailleurs, et surtout l'essentiel de ce dont vous avez besoin a déjà été écrit par d'autres. Recopier ce code dans chaque projet serait absurde : autant de copies, autant de versions à corriger.

import répond exactement à cet ennui. L'instruction va chercher un module, c'est-à-dire un fichier Python écrit ailleurs, et rend son contenu utilisable ici. Ce module peut venir de la bibliothèque standard livrée avec Python, d'un package installé, ou d'un autre fichier de votre projet : la même ligne sert dans les trois cas.

PYTHON
# json est livré avec Python, il n'y a rien à installer
import json

# Le nom du module devient le préfixe de tout ce qu'il contient
donnees = json.loads(reponse)

Ce préfixe n'est pas une contrainte, c'est un repère. En croisant json.loads au milieu de trois cents lignes, on sait d'où vient la fonction sans remonter en haut du fichier ni ouvrir la documentation.


Les trois écritures

La ligne d'import s'écrit de trois manières, et ce choix décide de ce que vous manipulez dans tout le reste du fichier.

ÉcritureCe qu'elle donne
import jsonLe module entier, accessible via json.
from json import loadsUne seule fonction, accessible sans préfixe
import numpy as npLe module entier, sous un nom raccourci

La première garde l'origine visible partout, au prix d'un préfixe répété. La deuxième ramène un seul élément et allège l'écriture, mais l'origine ne tient plus que dans la ligne d'import. La troisième renomme au passage : np pour numpy ou pd pour pandas sont des conventions si répandues qu'elles se lisent comme le nom complet.

Une quatrième forme existe, from module import *, qui déverse tout dans l'espace courant. Elle est déconseillée sans exception : plus rien n'indique d'où vient un nom, et deux modules qui exposent le même nom s'écrasent silencieusement, sans erreur ni avertissement.


Où Python va chercher

Quand vous écrivez import json, Python ne devine rien : il parcourt une liste de dossiers dans un ordre fixe et s'arrête au premier qui porte ce nom. Le dossier du fichier lancé vient d'abord, puis les chemins de l'environnement, puis les paquets installés.

Cet ordre explique la plupart des ModuleNotFoundError, mais aussi une famille de bugs autrement incompréhensibles. Puisque le dossier courant passe en premier, un de vos fichiers nommé comme une bibliothèque connue prend la place de celle-ci.

Attention

Un fichier json.py posé dans un projet détourne vers lui tous les import json du dossier, bibliothèque standard comprise. Les erreurs qui suivent parlent d'un attribut manquant, jamais du nom du fichier, et la piste peut se chercher une heure.

L'environnement compte autant que le nom. Un paquet installé avec pip n'existe que dans l'environnement virtuel où l'installation a eu lieu. Un import qui fonctionnait hier et échoue aujourd'hui vient souvent de là : ce n'est pas le code qui a changé, c'est l'interpréteur qui lance le script.


Ce qui se passe au premier import

Un import ne se contente pas de rendre un nom disponible : Python ouvre le fichier du module, l'exécute de haut en bas une seule fois, puis range le résultat dans un cache.

La conséquence surprend souvent : tout ce qu'un module écrit à son niveau supérieur s'exécute chez celui qui l'importe. Un print laissé après un test, une connexion ouverte, une longue préparation de données, tout part à l'import. C'est pour cette raison qu'un fichier destiné à être exécuté range son code de lancement derrière un point d'entrée, la fameuse ligne if __name__ == "__main__":.

Le cache, lui, rend les imports répétés gratuits. Un module importé dans dix fichiers n'est chargé qu'une fois par exécution. Multiplier les lignes d'import ne coûte donc rien en performance, seulement en lisibilité le jour où elles ne servent plus.

Bon à savoir

Ce cache déroute en session interactive : modifier un module puis relancer son import ne change rien, Python le voit déjà chargé et ne relit pas le fichier. Il faut redémarrer la session, ou passer par importlib.reload.


Où placer ses imports

La PEP 8 demande de rassembler tous les imports en haut du fichier, groupés en trois blocs séparés par une ligne vide : bibliothèque standard, paquets tiers, puis modules du projet. L'intérêt est de voir en cinq secondes ce dont ce fichier dépend, sans le parcourir.

Deux situations justifient de descendre un import dans le code. Rompre une dépendance circulaire, quand deux modules s'importent mutuellement sans qu'aucun parvienne à finir de se charger. Et différer un chargement coûteux, pour ne le payer que si la branche concernée est empruntée.


Questions fréquentes

Question

Pourquoi Python ne trouve-t-il pas mon module ?

Le message ModuleNotFoundError donne le nom exact recherché, et l'explication est presque toujours l'une des trois suivantes : le paquet n'est pas installé dans l'environnement actif, le nom d'installation diffère du nom d'import (pip install pillow donne import PIL), ou votre fichier se trouve dans un dossier que Python n'explore pas.

Question

Faut-il importer tout le module ou seulement ce qu'on utilise ?

Importer le module entier garde l'origine sous les yeux à la lecture, ce qui vaut cher sur un fichier long. Importer une fonction précise allège l'écriture quand elle revient vingt fois. Les deux sont corrects, et rester cohérent dans un même fichier compte davantage que le choix.

Question

Un import peut-il ralentir le démarrage ?

Oui, certaines bibliothèques de calcul mettent près d'une seconde à se charger, et cette seconde est payée avant la première ligne utile. Sur un script en ligne de commande qui doit répondre vite, déplacer un import lourd à l'intérieur de la fonction qui en a besoin devient une optimisation légitime.

Termes connexes

Découvrez notre glossaire Python

Parcourez les termes et définitions les plus couramment utilisés dans le domaine du développement avec Python.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.