Imagine the following scenario. You're writing some module consisting of multiple files. As you're writing the code, eventually, you arrive at a situation where multiple files (let's say main.py
and side.py
) import each other, leading to a recursive import, a no-go.
module/
main.py
side.py
You decide to split main
into multiple files: base.py
and advanced.py
. The former contains merely the basic definitions from main.py
and does not make use of side
nor any other submodules; other submodules which wish to make use of main
should be satisfied with importing this. The latter (advanced.py
) can freely import anything from side
, but since side
does not make use of advanced
, there is no recursion. This resolves the recursive import.
Now, you're left with the following package structure:
module/
side.py
base.py
advanced.py
It makes sense to put base
and advanced
into a subfolder main
(thus creating a submodule), because this at least partially preserves the original package structure. Thus we obtain
module/
side.py
main/
base.py
advanced.py
But now consider a third file third.py
, which originally imported the entire main
:
from .main import *
The interface to main
was broken by the aforementioned "recursion-fixing" operator. So, how does one restore the original interface, that is, how does one make from .main import *
import everything from both base
and advanced
?
Example
Original main.py
:
from .side import *
class A:
pass
class B(C):
pass
Original side.py
:
from .main import *
class C:
pass
class D(A):
pass
After restructuring, main
is split into two files:
# base.py
class A:
pass
# advanced.py
from module.side import *
class B(C):
pass
And side
should now be importing main.base
instead of main
:
# new side.py
from .main.base import *
class C:
pass
class D(A):
pass
Here are some not totally satisfactory solutions/ideas:
__init__.py
shenaningans
Create __init__.py
in the main
submodule, and place the following into it (solution from Implicit import from submodules):
from .base import *
from .advanced import *
The problem with this is that again introduces a recursive import: recall that side
makes use of main.base
, thus somewhere there, there is a line of code
from .main.base import *
which would invoke the __init__.py
, causing side
to import from advanced
as well. Which we wanted to avoid. More specifically, putting the following into the python interpreter
from module.side import *
outputs the following error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".../module/side.py", line 2, in <module>
from .main.base import *
File ".../module/main/__init__.py", line 2, in <module>
from .advanced import *
File ".../module/main/advanced.py", line 4, in <module>
class B(C):
NameError: name 'C' is not defined
The reason being that, when loading advanced
, it attempts to load side
. But since side
is "already loaded" (or rather is currently being loaded), to avoid infinite recursion, python merely skips over it. But then class C
, which is required by advanced
, is not loaded.
Instead put the shenaningans in all.py
Instead of putting the aforementioned two lines of code inside a __init__.py
, put it in another file all.py
. Now, when one wants to import everything from main
, one writes
from .main.all import *
This is still not the same as from .main import *
, so whenever such "recursion-fixing" restructuring of the package takes place, one would have to look for all such imports and rewrite them (by appending .all
).