ImportError

The import found the module but not what you asked for — a typo, a name that moved or was removed, a relative import outside a package, or a circular import that asked too early.

InheritsBaseException›Exception›ImportError
Import / syntax exceptionPython 3 (all)Live demo
ImportError(*args, namename — Keyword-only. The module involved — for "cannot import name", the module that lacked the name.type: str | None · default: None=None, pathpath — Keyword-only. The file that triggered the error, when there is one (None for built-in modules).type: str | None · default: None=None)
Raised by
from module import name, relative imports, a module that raises it on import
Message
cannot import name 'x' from 'mod' (/path/to/mod.py)
Quick fix
check the spelling / the library's version; break circular imports
Watch out
ModuleNotFoundError is a subclass — except ImportError catches both

Demo

Live evaluation
from itertools import <name>, run through exec() so you can type the name. itertools is built into every CPython, so the message ends in (unknown location) instead of a file path.
Try:
Inputs
namestra name to import
Code
import keyword
name = 'chain'
if not name.isidentifier() or keyword.iskeyword(name):
    raise ValueError('not a valid name')
exec(f'from itertools import {name}')
'imported ' + name
Result
'imported chain'

Try batchd and izip_longest: CPython compares the missing name with everything in the module and adds Did you mean: 'batched'? when one is close enough. izip has no close match — it was removed in Python 3 (use the built-in zip). Names are case-sensitive: Chain fails but gets the hint (one case flip is cheap), while CHAIN is five changes away and gets none.

Constructor

NameTypeRequiredDescription
*argsobjectnoUsually one message string (also available as e.msg).
namestr | Noneno (None)Keyword-only. The module involved — for "cannot import name", the module that lacked the name.
pathstr | Noneno (None)Keyword-only. The file that triggered the error, when there is one (None for built-in modules).

Attributes

AttributeTypeMeaning
namestr | NoneThe module name. For "cannot import name 'x' from 'mod'" this is 'mod'.
pathstr | NonePath of the module file, or None (built-in modules, relative-import errors).
msgstrThe message text, same as str(e) when the exception was built with one argument.
argstupleThe constructor arguments; name and path are not included.

Common patterns

Optional feature with a fallback
Import the newer or faster implementation when available, otherwise a local one.
try:
    from itertools import batched          # Python 3.12+
except ImportError:
    def batched(iterable, n):
        it = iter(iterable)
        while chunk := tuple(islice(it, n)):
            yield chunk
Break a circular import
Import the module (not the name) at the top, or move the import into the function that needs it — by then both modules are fully loaded.
# orders.py
import customers          # not: from customers import lookup

def total(order):
    return customers.lookup(order.customer_id).discount
Run package code as a module
Relative imports need a package context: run python -m package.module from the project root instead of python package/module.py.
# app/cli.py
from .config import load   # works with: python -m app.cli

Examples

1. Name removed in Python 3
from itertools import izip
Returns
ImportError: cannot import name 'izip' from 'itertools' (unknown location)
2. Typo gets a suggestion
from itertools import pairwise, batchd
Returns
ImportError: cannot import name 'batchd' from 'itertools' (unknown location). Did you mean: 'batched'?
3. Renamed in Python 3
from itertools import izip_longest
Returns
ImportError: cannot import name 'izip_longest' from 'itertools' (unknown location). Did you mean: 'zip_longest'?
4. e.name is the module
try: from itertools import izip except ImportError as e: r = (type(e).__name__, e.name, e.path) r
Returns
('ImportError', 'itertools', None)
5. Relative import in a script
from . import helpers
Returns
ImportError: attempted relative import with no known parent package
6. Circular import
import os, sys with open('ie_cyc_a.py', 'w') as f: f.write('from ie_cyc_b import g\ndef f():\n return 1\n') with open('ie_cyc_b.py', 'w') as f: f.write('from ie_cyc_a import f\ndef g():\n return 2\n') sys.path.insert(0, os.getcwd()) try: import ie_cyc_a except ImportError as e: msg = e.msg finally: sys.path.remove(os.getcwd()) msg.split(' (most')[0]
Returns
"cannot import name 'f' from partially initialized module 'ie_cyc_a'"
7. except ImportError catches ModuleNotFoundError
try: import no_such_pkg_ie except ImportError as e: r = type(e).__name__ r
Returns
'ModuleNotFoundError'
8. Raising it with name and path
e = ImportError('plugin failed to load', name='acme.plugin', path='plugins/acme.py') (str(e), e.name, e.path)
Returns
('plugin failed to load', 'acme.plugin', 'plugins/acme.py')

Pitfalls

1. from-imports make circular imports fail
In a cycle, the second module runs while the first is only half executed. from a import f needs f to exist already; import a only needs the module object, and a.f is looked up later, when it exists.
from … import
import os, sys
with open('ie_p1_a.py', 'w') as f:
    f.write('from ie_p1_b import g\ndef f():\n    return 1\n')
with open('ie_p1_b.py', 'w') as f:
    f.write('from ie_p1_a import f\ndef g():\n    return f() + 1\n')
sys.path.insert(0, os.getcwd())
try:
    import ie_p1_a
except ImportError as e:
    r = 'circular import' in str(e)
finally:
    sys.path.remove(os.getcwd())
r
True
import module
import os, sys
with open('ie_p2_a.py', 'w') as f:
    f.write('import ie_p2_b\ndef f():\n    return 1\n')
with open('ie_p2_b.py', 'w') as f:
    f.write('import ie_p2_a\ndef g():\n    return ie_p2_a.f() + 1\n')
sys.path.insert(0, os.getcwd())
try:
    import ie_p2_a
    r = ie_p2_a.ie_p2_b.g()
finally:
    sys.path.remove(os.getcwd())
r
2
2. Old Python 2 names
Tutorials written for Python 2 import names that were removed or renamed. The fix is the Python 3 spelling, not installing anything.
izip
from itertools import izip
list(izip('ab', 'xy'))
ImportError: cannot import name 'izip' from 'itertools' (unknown location)
built-in zip
list(zip('ab', 'xy'))
[('a', 'x'), ('b', 'y')]

When to use

Use it
  • Catching it for optional dependencies and version-dependent names (compat shims)
  • Raising it (with name=/path=) from a plugin loader when a plugin cannot be loaded
Reach for something else
  • A bare except ImportError around a big block → it also hides import errors inside the modules you import
  • Only the "module not installed" case → catch ModuleNotFoundError

Notes

CPython impl
Python/ceval.c import_from() — builds "cannot import name …"; the path in parentheses is the module file, or "unknown location" for built-in modules
Did you mean
Added by the traceback printer (3.12+), not part of str(e)
Catch via
except ImportError also catches ModuleNotFoundError
Shadowing
3.13 adds "(consider renaming …)" when your own file hides a standard-library module of the same name

FAQ

The module Y was found, but has no attribute X. Check, in order: the spelling and case of X; whether X exists in the version of Y you have installed (it may be newer, renamed or removed — compare the library's changelog); whether the Y that was imported is the one you expect (print Y.__file__ — a local file can shadow a package); and whether Y and your module import each other (circular import — the message then says "partially initialized module").

History

3.3
Added the name and path attributes.