ImportError: cannot import name 'X' from 'Y'
1 · The lesson
readWhat this error means
Python found and successfully imported moduleY, but when it tried to bind the name X from inside Y, that name was not there. Either X does not exist in Y (typo, renamed, removed in this version), or Y is in the middle of importing and X has not yet been defined — that is the circular import case.
When you see it
Traceback (most recent call last):
File "app.py", line 1, in <module>
from collections import OrderedDic
ImportError: cannot import name 'OrderedDic' from 'collections'Newer Python versions also tell you where they looked:
ImportError: cannot import name 'soft_unicode' from 'markupsafe' (/usr/lib/python3/site-packages/markupsafe/__init__.py)
Why it happens
Cause 1 — typo or wrong case. OrderedDic instead of OrderedDict, Path from os instead of pathlib.
Cause 2 — version mismatch. The symbol existed in an older or newer version of the package than the one you have installed. markupsafe.soft_unicode was removed in 2.1; Jinja2 < 3.1 still expects it.
Cause 3 — circular import. Module A imports from B at the top, B imports from A at the top. Whichever Python loaded first is only half-initialised when the other tries to read from it.
# a.py from b import helper def thing(): return helper() + 1 # b.py from a import thing # boom: a is mid-import, has no `thing` yet def helper(): return 0
How to fix it
For typos. Check the docs or use dir(Y):
import collections print([n for n in dir(collections) if 'dict' in n.lower()])
For version mismatches. Check what's installed and pin compatible versions:
python -m pip show markupsafe jinja2 python -m pip install "markupsafe<2.1" # or upgrade jinja2 instead
For circular imports. Three reliable fixes, cleanest first.
1. Extract the shared piece into a third module. Both A and B import from common.py. No cycle.
2. Move the import inside the function that needs it. The import is deferred until call time, by which point both modules are fully loaded.
python
# a.py
def thing():
from b import helper
return helper() + 1
3. Import the module, not the name. import b then b.helper(). Python is more forgiving about half-loaded modules accessed via attribute lookup than about names bound at import time.
When you'd actually see this in real code
- Upgrading a dependency (Django, Flask, SQLAlchemy) and a third-party plugin pinned to an older API breaks.
- Two modules in your own project that both reference each other's models or schemas.
- Copying an
importfrom a code sample written against a newer version of the library.
Related errors
ModuleNotFoundError: No module named 'Y'—Yitself can't be found. See error-modulenotfounderror.AttributeError: module 'Y' has no attribute 'X'— same root cause as ImportError, but triggered byY.Xinstead offrom Y import X.
See Also
- All Python errors — the full index, by type and by when it happens.
- Modules and imports — how import binding works.
- Virtual environments — pinning package versions.
- cheat-imports — fast lookup for import patterns.