Definition
You run a script that starts with a plain import, and it stops cold before its first useful line. That is ModuleNotFoundError firing: Python walked through every place it knows how to look for a module, finding neither a file nor a package under that name.
# pip install requests was run right before this
import requests
# ModuleNotFoundError: No module named 'requests'This error has only had its own name since Python 3.6; before that, it shared a single exception with a related case, ImportError, with no way to tell a missing module from one that exists but fails to load. The distinction matters for recovery code: catching ModuleNotFoundError only catches the pure absence, catching ImportError catches both, since the first inherits from the second.
Where Python actually looks
Saying Python found nothing "anywhere" still says nothing until that word is spelled out: it actually consults a precise list of folders, called sys.path, built when the program starts and always walked in the same order.
| Rank | What gets searched |
|---|---|
| 1 | The folder of the script that was launched |
| 2 | The paths declared in the PYTHONPATH variable |
| 3 | The standard library of the running interpreter |
| 4 | The packages installed for that same interpreter |
Two words in that table explain a good half of the cases seen in practice. "Launched", at the first rank, means the folder of the file that was executed, not the folder the terminal happens to sit in: an in-house module that imports perfectly from the project root can become unfindable from a subfolder, the root having left the list.
"Running", at ranks three and four, means the interpreter executing the code at that exact moment, not whichever one was used to install anything. This is the most frequent cause, the one that trips up nearly everyone once: an installation that succeeded, followed by an import that fails anyway.
The four causes, by frequency
The first connects to the "running" interpreter: the package was installed by an interpreter different from the one running the code, for instance a virtual environment forgotten at launch. Two lines settle it.
import sys
print(sys.executable) # the path of the interpreter running this scriptIf the printed path does not match the environment where the installation happened, the cause is found: rerun the script with the right interpreter, or reinstall the package into the one actually in use.
An editor that kept an old interpreter cached reproduces this trap without warning: the install reports success, the import fails right after, and nothing says the two never spoke to the same Python.
The second cause comes down to the name itself: the name of the package installed and the name of the module imported are two independent strings, chosen separately by the authors, with no guarantee they look alike.
| What gets installed | What gets imported |
|---|---|
| pillow | PIL |
| beautifulsoup4 | bs4 |
| python-dateutil | dateutil |
| scikit-learn | sklearn |
The third cause comes from a file that, without meaning to, mistakes itself for a library: a random.py sitting next to the script hides the standard module of the same name, since the current folder holds the first rank in the table above. The error then surfaces from an internal import, at a spot in the traceback with no apparent link to the offending file.
print(module_name.__file__) prints the exact path of the file loaded under that name: if it points into your own folder rather than the standard library, the name is colliding.
The fourth cause is the launch folder: importing an in-house module assumes starting from the project root, or going through the -m option. From a subfolder, a script loses that root, and every internal import fails at once.
Telling it apart from its neighbours
Three errors look alike at first glance, and yet they point towards opposite fixes.
| Error | What it reports | Where to look |
|---|---|---|
ModuleNotFoundError | No module under that name | Environment, installation |
ImportError | The module exists, the name asked after from is not in it | Package version |
| NameError | The name was never defined | A forgotten import |
That last row is worth pausing on: forgetting the import produces a name error, not an import error, at the moment the variable is read further down. Knowing which of the three shows up says right away whether something needs installing or a line needs adding at the top of the file.
Frequently asked questions
The installation succeeded, why does the import still fail?
Because the installation and the execution did not target the same interpreter, which happens as soon as a virtual environment is involved. Compare the path of sys.executable with the one of the environment used to install: nine times out of ten, the two differ.
Should this error be caught?
Only for a genuinely optional dependency, one the program can do without. A try followed by an except then allows falling back on another solution or printing a clear message. For a required dependency though, let the exception travel up unchanged: it is already more explicit than any workaround written by hand.
My module sits right next to the script, why is it still not found?
Because "next to the current file" and "in the launch folder" name two different things, and it is the second one that matters to Python. Run the program from the project root rather than from a subfolder, or declare that folder as a package, and check that no file name collides with a library already installed.