TL;DR
All 51 popular Python repos I checked (1,000+ GitHub stars each) have circular import chains between files; in the median one, 16.4% of production files sit inside one.
A Python circular import only fails with "partially initialized module" when a name is read from a module that has not finished running, such as a module-level from x import y , a base class, or a decorator that runs on import.
Django has a 179-file import cycle and imports fine, because most of its cycles go through imports inside functions or imports used only for type hints.
Fixes, in order: move the shared code to a third module, import the module instead of the name (with from __future__ import annotations ), put type-only imports under TYPE_CHECKING , or import inside the function.
This is the error that sends people searching:
ImportError: cannot import name 'User' from partially initialized module 'shop.models' (most likely due to a circular import)
Enter fullscreen mode
Exit fullscreen mode
The usual advice is "you…