Report #14565
[bug\_fix] ImportError: cannot import name 'X' from partially initialized module 'Y' \(most likely due to a circular import\)
Restructure the code to remove the circular dependency by moving the import inside the function/method where it's used \(lazy import\) or refactoring shared code into a separate third module that both original modules can import. The root cause is that when Python begins importing a module, it immediately adds the module object to \`sys.modules\` to prevent infinite recursion, but the module's code hasn't finished executing yet \(it's 'partially initialized'\). If during this execution, the module \(or a submodule\) attempts to import from another module that in turn tries to import from the original partially initialized module, Python detects the circularity. The import system allows the second import to proceed \(using the partially initialized module from sys.modules\), but if it tries to access names that haven't been defined yet \(because the first module's execution is paused at the import line\), it raises ImportError. Moving imports to function level delays the import until after all modules have initialized, breaking the circularity at import time.
Journey Context:
You have \`models.py\` that defines database models and needs to import \`serialize\` from \`utils.py\` for a method. \`utils.py\` needs to import the \`Model\` class from \`models.py\` for type hints. You run your app and get \`ImportError: cannot import name 'serialize' from partially initialized module 'utils'\`. You stare at the code confused because both files look fine. You add print statements at the top of each file and see that \`models.py\` prints, then \`utils.py\` prints, then the error occurs. You realize that when \`models.py\` starts importing, it triggers \`utils.py\` to load, which then tries to import \`models\` again, but \`models\` is only partially initialized \(it's sitting at the import line in \`models.py\`\). You search and find PEP 384 or import system docs. You consider using \`if TYPE\_CHECKING\` for the type hints, but the \`utils.py\` actually needs the Model class at runtime too. You decide to move the import inside the function in \`utils.py\` that uses Model: \`def process\(model\): from .models import Model; ...\`. Now when \`utils.py\` is first imported at the top level of \`models.py\`, it doesn't try to import Model immediately. Later, when the function is actually called, all modules have finished initializing, and the import succeeds. Alternatively, you could create a \`types.py\` file that both import from, but the lazy import fix works immediately.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T21:50:44.684581+00:00— report_created — created