ImportError in Python: the import that fails

ImportError reports a module that loaded fine but a name missing inside it. Version, case, a same-named file or a circular import: four causes cover it.
6 min read
Believemy logo

Definition

You copy a line out of the documentation, you run the script, and Python answers that this name does not exist. The library is installed, though, and it has just loaded without complaint. So who is wrong, the documentation or the machine?

Neither of them: ImportError describes one precise situation. Python found the requested module, opened it and ran it, but the name written after import is not in there. This exception therefore speaks of no missing module, only of contents that disappoint.

PYTHON
# The math module exists and loads without the slightest problem...
from math import square_root
# ... but no name "square_root" can be found in it.

# ImportError: cannot import name 'square_root' from 'math'

The message reads in two halves, and the second one is the one people skip. The first names what you asked for; the second, after from, names the module actually opened to look for it. When the first half looks right, the culprit is in the second: the file that loaded is not the one you believed.

Another marker: this error comes from the from module import name form. A bare import module asks for no particular name, and when it fails, it fails earlier, for want of finding the module at all: Python then raises a ModuleNotFoundError.


Two errors, one family

The two names are all the easier to mix up because the language brought them together: since Python 3.6, ModuleNotFoundError has been a subclass of ImportError, and a single except ImportError catches both. Handy in the code, misleading when reading it. The table separates them, along with a third error that gets blamed on them by mistake.

SituationError raisedWhere to look
The module cannot be foundModuleNotFoundErrorInstallation, package name, environment
The module loads, the name is missingImportErrorFile contents, version, letter case
The name is missing after a successful importAttributeErrorThe access line, not the import line

The third row is the surprising one. An import requests followed by a misspelled call produces no ImportError at all: the import succeeded, and it is the access that fails twenty lines further down. The name of the error says when Python lost the thread, and that moment guides better than the line where everything stops.


The causes that keep coming back

The most frequent one is a name that moved. A library reorganises itself between major versions: an object goes off into a submodule, a function changes place. Code written for the previous version breaks on the very first run, although you touched nothing yourself. Comparing the installed version with the one in the documentation open in front of you settles a good half of the cases.

Next comes letter case. Python separates uppercase from lowercase right down to an import, where macOS and Windows see Utils.py and utils.py as one single file. A project that imports cleanly on your laptop can therefore fail on its first deployment to a Linux server, over a single letter.

Then there is a file of your own taking the place of the real one. Python looks first in the folder the script was launched from: naming a file json.py or random.py is enough for it to go ahead of the genuine library, and then for Python not to find in it what it came for.

Warning

That last case often costs an hour, because the message names the official library and never your own file. Before doubting a library, read the path shown in the error: if it points at a file of your own project, renaming that file is all it takes.


The circular import

One last case throws everybody, because the requested name really does exist exactly where Python claims not to find it. The explanation is about timing: two files import each other, and by the time the first one asks the second for something, that second file is still halfway through its loading. The name exists in the file, not yet in memory.

PYTHON
# basket.py
from invoice import issue     # this file asks for invoice.py...

# invoice.py
from basket import Basket     # ... which asks back for basket.py, still loading

# ImportError: cannot import name 'Basket'
# from partially initialized module 'basket'

The words partially initialized module are the signature of the cycle: as long as they show up, there is no point hunting for a typo, because there is none.

Three ways out exist. Moving the import inside the function that needs it delays the loading until the call. Importing the whole module, then writing basket.Basket at the point of use, works too. Pulling the shared part into a third file is the only one that treats the cause: a cycle reveals a shaky split between two responsibilities, and it will come back in another shape if you work around it.


Frequently asked questions

Question

Should an ImportError ever be caught?

One case justifies it: the optional dependency, the one that improves the program without being essential to it. A try block around the import, with a fallback value in the except, lets the rest keep running. Elsewhere, catching it hides an incomplete installation and pushes the crash out to a message that no longer says anything about the cause.

Question

Why does the error only show up in production?

Because the machine is not the same, and the gap almost always comes down to one of three points: a different library version, a case-sensitive file system, a package installed by hand one day and never declared anywhere. Pinning the versions in a dependency file, then replaying the imports in a fresh virtual environment, reveals the problem before the users do.

Question

What if the name really is in the file?

Read in the traceback the path of the module that was actually loaded, which Python prints between quotes. Nine times out of ten it is not the file open in your editor but a namesake: an old package left installed, a forgotten test folder, a script sitting in the current directory. The path settles in a second a question that would otherwise take the morning. The Python course spends a long time on this way of reading errors.

Related terms

Discover our python glossary

Browse the terms and definitions most commonly used in development with Python.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.