Edit
I investigated this in more detail and came to the conclusion that this is a mistake both in the basic Python documentation and in the Python documentation. Further information is available in this question and answer .
Python PEP 8 points to a clear preference for absolute relative imports. This problem has a workaround related to relative imports, and there is a possible fix in imports.
In my original answer below are examples and workarounds.
Original answer
The problem, as you deduced correctly, is circular dependence. In some cases, Python can handle them just fine, but if you get too many nested imports, it has problems.
For example, if you have only one level of a package, it is actually quite difficult to make it break (without mutual import), but as soon as you insert packages, it looks more like mutual import, and it starts to become difficult to make it work. Here is an example that causes an error:
level1/__init__.py
from level1.level2 import Base
level1/level2/__init__.py
from level1.level2.base import Base from level1.level2.a import A
level1/level2/a.py
import level1.level2.base class A(level1.level2.base.Base): pass
level1/level2/base
class Base: pass
A bug can be “fixed” (for this small case) in several ways, but many potential fixes are fragile. For example, if you do not need to import A in the file level2 __init__ , deleting this import will fix the problem (and your program may later execute import level1.level2.aA ), but if your package becomes more complex, you will see errors creeping in again.
Python sometimes does a good job of creating these complex import jobs, and the rules for when they will and will not work are not at all intuitive. One general rule is that from xxx.yyy import zzz can be more forgiving than import xxx.yyy followed by xxx.yyy.zzz . In the latter case, the interpreter had to complete the binding of yyy to the xxx namespace when it was time to get xxx.yyy.zzz , but in the first case, the interpreter could move the modules in the package before, for the full package namespace.
So, for this example, the real problem is bare imports in a.py This can be easily fixed:
from level1.level2.base import Base class A(Base): pass
Constantly using relative imports is a good way to enforce this use from ... import for the simple reason that relative imports do not work without from'. To use relative imports with the example above, from'. To use relative imports with the example above, level1 / level2 / a.py` should contain:
from .base import Base class A(Base): pass
This breaks the problematic import cycle, and everything else works fine. If the imported name (for example, Base) is too confusing for the generic name, if it does not have a prefix with the name of the source module, you can easily rename it when importing:
from .base import Base as BaseModel class A(BaseModel): pass
Although this fixes the current problem, if the package structure becomes more complex, you might want to consider using relative imports more generally. For example, level1/level2/__init__.py could be:
from .base import Base from .a import A