ModuleNotFoundError en Python : le module que Python ne trouve pas

ModuleNotFoundError signale que Python n'a trouvé aucun module portant le nom demandé. Presque toujours une question d'environnement, pas de code.
5 min de lecture
Believemy logo

Définition

Vous lancez un script qui commence par un simple import, et il s'arrête net avant sa première ligne utile. C'est ModuleNotFoundError qui vient de se déclencher : Python a parcouru tous les endroits où il sait chercher un module, sans y trouver ni fichier ni paquet portant ce nom.

PYTHON
# pip install requests a pourtant été lancé avant ceci
import requests

# ModuleNotFoundError: No module named 'requests'

Cette erreur porte un nom à part depuis Python 3.6 seulement ; avant, elle partageait une seule exception avec un cas voisin, ImportError, sans distinguer un module absent d'un module qui existe mais refuse de se charger. La distinction compte pour le code de récupération : intercepter ModuleNotFoundError ne rattrape que l'absence pure, intercepter ImportError rattrape les deux, puisque la première en hérite.


Où Python cherche, exactement

Dire que Python n'a rien trouvé « nulle part » ne veut rien dire tant qu'on ignore ce que ce mot recouvre : il consulte en réalité une liste précise de dossiers, nommée sys.path, construite au lancement du programme et toujours parcourue dans le même ordre.

RangCe qui est fouillé
1Le dossier du script lancé
2Les chemins déclarés dans la variable PYTHONPATH
3La bibliothèque standard de l'interpréteur en cours
4Les paquets installés pour ce même interpréteur

Deux mots de ce tableau expliquent une bonne moitié des cas rencontrés en pratique. « Lancé », au premier rang, désigne le dossier du fichier exécuté, pas celui où l'on se trouve dans un terminal : un module maison qui s'importe très bien depuis la racine d'un projet peut devenir introuvable depuis un sous-dossier, la racine ayant quitté la liste.

« En cours », aux rangs trois et quatre, désigne l'interpréteur qui exécute le code à cet instant, pas celui qui a servi à installer quoi que ce soit. C'est la cause la plus fréquente, celle qui déroute presque tout le monde une fois : une installation réussie, suivie d'un import qui échoue quand même.


Les quatre causes, par fréquence

La première rejoint l'interpréteur « en cours » : le paquet a été installé par un interpréteur différent de celui qui exécute le code, par exemple un environnement virtuel oublié au lancement. Deux lignes suffisent pour trancher.

PYTHON
import sys
print(sys.executable)  # le chemin de l'interpréteur qui exécute ce script

Si le chemin affiché ne correspond pas à l'environnement où l'installation a eu lieu, la cause est trouvée : relancez le script avec le bon interpréteur, ou réinstallez le paquet dans celui réellement utilisé.

Attention

Un éditeur qui a gardé en mémoire un ancien interpréteur reproduit ce piège sans prévenir : l'installation affiche un succès, l'import échoue juste après, et rien ne dit qu'ils n'ont pas parlé au même Python.

La deuxième cause tient au nom lui-même : le nom du paquet installé et le nom du module importé sont deux chaînes indépendantes, choisies séparément par les auteurs, sans qu'elles se ressemblent forcément.

Ce qui s'installeCe qui s'importe
pillowPIL
beautifulsoup4bs4
python-dateutildateutil
scikit-learnsklearn

La troisième cause vient d'un fichier qui se prend, sans le vouloir, pour une bibliothèque : un random.py posé à côté du script masque le module standard du même nom, puisque le dossier courant occupe le premier rang du tableau vu plus haut. L'erreur remonte alors depuis une importation interne, à un endroit du traceback sans rapport apparent avec le fichier fautif.

Bon à savoir

print(nom_module.__file__) affiche le chemin exact du fichier chargé sous ce nom : s'il pointe vers votre propre dossier plutôt que vers la bibliothèque standard, le nom est en collision.

La quatrième cause tient au dossier de lancement : importer un module maison suppose de partir de la racine du projet, ou de passer par l'option -m. Depuis un sous-dossier, un script perd cette racine, et tous ses imports internes échouent d'un coup.


La distinguer de ses voisines

Trois erreurs se ressemblent au premier coup d'oeil, et pourtant elles pointent vers des corrections opposées.

ErreurCe qu'elle signaleOù chercher
ModuleNotFoundErrorAucun module de ce nomEnvironnement, installation
ImportErrorLe module existe, le nom réclamé après from n'y est pasVersion du paquet
NameErrorLe nom n'a jamais été définiUn import oublié

La dernière ligne mérite qu'on s'y arrête : oublier l'import produit une erreur de nom, pas une erreur d'import, au moment où la variable est lue plus loin. Savoir laquelle des trois s'affiche dit s'il faut installer quelque chose ou ajouter une ligne en haut du fichier.


Questions fréquentes

Question

L'installation a réussi, pourquoi l'import échoue-t-il quand même ?

Parce que l'installation et l'exécution n'ont pas visé le même interpréteur, ce qui arrive dès qu'un environnement virtuel entre en jeu. Comparez le chemin de sys.executable avec celui de l'environnement utilisé pour installer : neuf fois sur dix, les deux diffèrent.

Question

Faut-il rattraper cette erreur ?

Seulement pour une dépendance réellement facultative, celle dont le programme peut se passer. Un try suivi d'un except permet alors de basculer sur une solution de repli ou d'afficher un message clair. Pour une dépendance indispensable, laissez l'exception remonter telle quelle : elle est déjà plus explicite que n'importe quel contournement écrit à la main.

Question

Mon module est juste à côté, pourquoi reste-t-il introuvable ?

Parce que « à côté du fichier en cours » et « dans le dossier de lancement » désignent deux choses différentes, et c'est le second qui compte pour Python. Lancez le programme depuis la racine du projet plutôt que depuis un sous-dossier, ou déclarez ce dossier comme un paquet, et vérifiez qu'aucun nom de fichier n'entre en collision avec une bibliothèque déjà installée.

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.