Python ImportError: cannot import name X from Y
Fix ImportError: cannot import name when a symbol is missing, circular imports bite, or a local file shadows the installed package.
Symptoms
- ImportError: cannot import name X from Y
- The import works at the top level but fails when the module is imported by another
- It broke after renaming a function or moving code
Possible causes
- The symbol was renamed or removed in the installed version
- A circular import leaves the module partially initialised
- A local file shadows the package being imported
- The symbol is defined after the import statement inside a module that runs it
Diagnosis steps
Verify the symbol exists
python -c "import Y; print(hasattr(Y, 'X'))"Interpretation
If hasattr is False, the name is simply absent in this version.
Check where Y loads from
python -c "import Y; print(Y.__file__)"Interpretation
A path inside your project means shadowing, not a real package.
Look for circular dependency loops
Interpretation
If Y imports the module that imports Y, one side sees a half-built module during import.
Root cause
ImportError for a name means the target module exists but does not expose that attribute at import time. This happens when the symbol is absent in the installed version, when a circular import returns a partially initialised module, or when a local module shadows the intended package.
Fix
Import the symbol from its real location, lazy-import inside functions to break cycles, and move imports to the top of modules. Rename shadowing files and clear __pycache__. When a symbol moved, update to the new name or pin the dependency to the version that still exports it.
Verify the fix
Re-import the module and confirm the symbol resolves without error, then run the affected entry point to prove the whole chain works.
Symptoms
An import statement fails with cannot import name X from Y, even though the package installs fine. It frequently appears only in larger applications where modules import each other.
Diagnosis
Check the symbol and the module origin:
import Y
print(Y.__file__)
print(hasattr(Y, 'X'))
If __file__ is inside your tree, you are importing a local file. Otherwise a circular import can return a module that has not finished defining X.
Fix
Break cycles with local imports:
# a.py imports b.py, b.py imports a.py -> cycle
def handler():
from a import helper # deferred, avoids the cycle
return helper()
Rename shadowing files and update renamed symbols.
Verification
Run python -c "from Y import X"; it should succeed, and the application entry point should start without the ImportError.
Additional Notes
The name may exist yet not be importable because of a circular dependency, where the importing module runs before the imported one finishes defining the symbol. That is why the same import works from a script but fails inside a package that forms a cycle. Deferring the import into the function that needs it, or moving shared definitions into a lower-level module that neither side imports, breaks the cycle cleanly. Distinguishing a truly missing symbol from a partially initialised module matters, since the fixes are entirely different.