Python "cannot import name X from partially initialized module" (circular) in CI
By Kaveh Alemi·Latchkey
Python began importing a module, hit an import back to a module still mid-initialization, and the requested name was not defined yet. The interpreter labels the module "partially initialized" and points at a circular import.
What this error means
An import fails with "ImportError: cannot import name 'X' from partially initialized module 'Y' (most likely due to a circular import)". It reproduces deterministically based on import order.
python
ImportError: cannot import name 'User' from partially initialized module 'app.models'
(most likely due to a circular import) (/app/app/models/__init__.py)
Diagnose it: is it the build backend or a missing system library?
Python packaging failures in CI split into build-backend configuration problems and missing system headers. The traceback usually points at the backend even when the real cause is an absent -dev package.
Terminal
python -m pip install --upgrade pip build
python -m build --wheel 2>&1 | tail -40
# a compiler error naming a .h file is a system dependency, not a Python one# e.g. "Python.h: No such file" -> python3-dev# "openssl/ssl.h" -> libssl-dev
Common causes
Two modules import each other at module scope
Module A imports B at the top, B imports A at the top; whichever loads first is incomplete when the other needs a name from it.
A package __init__ eagerly imports submodules that import back
An __init__.py that imports everything can create a cycle when a submodule imports a name from the package root.
How to fix it
Defer the import to call time
Move the cross-import inside the function that needs it so the module is fully loaded before the name is accessed.
app/services.py
def get_user():
from app.models import User # imported lazily to break the cycle
return User.query.first()
Restructure to remove the cycle
Identify the two modules that import each other from the traceback.
Extract the shared name into a third module both can import.
Re-run so neither module depends on the other at load time.
How to prevent it
Avoid module-level imports between two interdependent modules.
Keep package __init__.py files thin to avoid eager cycles.
Move shared types into a leaf module both sides import.
Frequently asked questions
What causes Python "cannot import name X from partially initialized module" (circular) in CI?
There are 2 common causes: two modules import each other at module scope and a package __init__ eagerly imports submodules that import back. Module A imports B at the top, B imports A at the top; whichever loads first is incomplete when the other needs a name from it.
How do I fix Python "cannot import name X from partially initialized module" (circular) in CI?
There are 2 fixes depending on which cause you have: defer the import to call time and restructure to remove the cycle. Work through them in order, since the first is the most common.
What does Python "cannot import name X from partially initialized module" (circular) in CI actually mean?
An import fails with "ImportError: cannot import name 'X' from partially initialized module 'Y' (most likely due to a circular import)".
How do I stop Python "cannot import name X from partially initialized module" (circular) in CI happening again?
Avoid module-level imports between two interdependent modules. The prevention section lists 3 changes that keep it from recurring.