Python ImportError: cannot import name X from Y
Cannot import name from module
Verified against Python docs: Built-in Exceptions, Python docs: import system, PEP 328 (Imports) · Updated May 2026
> quick_fix
The module exists but does not expose the name you tried to import. Inspect what it actually exposes with python -c 'import target; print(dir(target))'. Common causes: typo, version mismatch where the symbol moved, or a circular import where the module is half-loaded.
# Reproduce the import in isolation
import target_module
print(dir(target_module)) # what's actually there
print(target_module.__file__) # which file Python loaded
print(target_module.__version__) # if exposedWhat causes this error
ImportError fires when Python successfully locates a module (so it's not ModuleNotFoundError) but the specific name in 'from x import y' is not in the module's namespace. Three primary causes: typo in the name; the package version installed does not include that symbol (renamed, removed, or moved); or a circular import where the module is partially loaded when your import runs.
How to fix it
- 01
step 1
Distinguish from ModuleNotFoundError
ModuleNotFoundError = the module itself isn't installed (errno-equivalent: import resolution failed). ImportError = module loads but the named symbol isn't there. Different fix paths.
# ModuleNotFoundError import notinstalled # pip install it # ImportError from requests import notreal # name doesn't exist on requests - 02
step 2
Inspect the module's actual namespace
Check dir() to see what's exposed. The expected name might be at a different path in newer/older versions, or you may have a typo.
python -c "import package.module; print(sorted(dir(package.module)))" # Or check version python -c "import package; print(package.__version__)" - 03
step 3
Check if you have the right module loaded
module.__file__ shows the actual file Python imported. If you have a local file named requests.py shadowing the installed package, Python loads yours instead and your name isn't there.
import requests print(requests.__file__) # Should be: .../site-packages/requests/__init__.py # If it's: ./requests.py - your local file is shadowing - 04
step 4
Find circular imports
If module A imports from B and B imports from A, the second import sees a half-built module. Restructure so shared types live in a third module both import from, or move the import inside the function that needs it.
# a.py from b import B # at top - circular! class A: def use(self): from b import B # lazy - works return B() - 05
step 5
Check version compatibility
Library APIs move between major versions. The symbol you're importing may have been renamed, deprecated, or relocated. Check the changelog for the version installed vs. the version your tutorial/docs reference.
# Old code (sklearn 0.x) from sklearn.cross_validation import train_test_split # New (sklearn 1.x) - moved to model_selection from sklearn.model_selection import train_test_split - 06
step 6
Check for namespace package vs regular package
If two installed packages share a top-level name (foo from pkg-a and foo from pkg-b), Python may load only one. Check for an __init__.py and use python -c "import foo; print(foo.__path__)".
pip show package-name python -c "import package; print(package.__path__)"
Why ImportError happens at the runtime level
Python's import machinery (importlib._bootstrap) executes the target module's top-level code, populating its __dict__. The 'from x import y' statement then performs getattr(module, 'y'). If y is not in module's namespace, CPython raises ImportError with the message 'cannot import name y from x'. During circular imports, the partial module is registered in sys.modules before its body finishes; the second import returns the partially-initialised object, and any name not yet defined at the point of the cycle triggers ImportError. The lookup is strict equality on the dict, not a structural search.
Common debug mistakes for ImportError
- Naming a local file requests.py or json.py, shadowing the standard or installed package.
- Top-level imports between two modules that need each other; restructure to a base module instead.
- Forgetting to bump pip install when reading newer docs that show a renamed import path.
- Catching ImportError broadly to silence errors, then debugging mysterious None values later.
- Mixing namespace packages and regular packages with the same top-level name; only one wins.
When ImportError signals a deeper problem
Frequent ImportErrors in a growing codebase signal a missing module-boundary discipline. The architectural fix is to enforce a layered structure: domain types in a base module, services that depend on types but not each other, and entry points that compose services. With this layout, circular imports become structurally impossible and version-specific imports get isolated to the few modules that touch external libraries. Tools like import-linter let you declare allowed dependency directions and fail CI on violations, catching imports that would otherwise compile fine but break later under realistic call orders.
Frequently asked questions
How is ImportError different from ModuleNotFoundError?
ModuleNotFoundError is a subclass of ImportError introduced in Python 3.6. It fires when the module itself can't be located on sys.path. ImportError (the parent) fires when the module loads but a 'from x import y' fails because y is not in x's namespace. Practically: ModuleNotFoundError = pip install something; ImportError = check version, check for typo, check for circular imports. Your except clause should match what you mean: catch ImportError to be lenient on both, ModuleNotFoundError to be strict.
What causes a circular import?
Module A imports from B at the top level. While Python is loading A, it pauses to load B. B's top level tries to import from A. Python sees A is mid-load, returns the half-built module object, and B's 'from A import name' fails because name hasn't been defined yet. Solutions: (1) extract shared types to a third module; (2) lazy-import inside the function that needs the symbol; (3) restructure to break the cycle, often by depending on abstractions (an interface in a base module) rather than concrete classes.
Why does my import work in REPL but fail when running the script?
REPL CWD is your shell's CWD. When you import locally-named modules, Python looks in sys.path which includes ''. The script may be invoked from a different directory and sys.path[0] is the script's directory, not yours. If the script imports a sibling module that depends on yet another sibling, the package layout matters. Convert to a proper package with an __init__.py and run via python -m mypackage.script instead of python script.py.
Should I always catch ImportError for optional dependencies?
Yes, when a dependency is genuinely optional. Catch ImportError at the top of your module and set a flag or fallback. Don't catch ImportError to silently ignore real bugs - that's how 'works on my machine' problems get shipped. The pattern: try to import, on ImportError set a feature flag to False, and at the call site raise a clear 'install package-name to enable feature X' error rather than a cryptic AttributeError later.