This is the tree:
X
|_ setup.py
|_ X
|_ someFile.py
|_ __init__.py (empty)
|_ Y
|_ __init__.py (empty)
|_ anotherFile.py
After running pip install -e .
, I can run the following commands anywhere on my system:
import X
from X import someFile
from X.Y import anotherFile
But I cannot run:
from X import Y
Y.anotherFile
-> Module X.Y has no attribute "anotherFile".
I can fix that by filling the lower-level __init__.py
with from X.Y import anotherFile
, but that seems a bit odd.
Why is that? Is my understanding of python packages wrong?
Disclaimer: Someone might have asked this before, but the question is so generic that I had difficulties finding the right post.
It's simple actually. For from X import Y
, the imported module is the __init__.py
file in directory Y
but not all other files.
But I think the real question is, Why?
Let's say anotherFile
is the only module you want, so you import anotherFile
by from X.Y import anotherFile
. But actually you have also imported X
and Y
. Although you cannot access them by X
or Y
, but if you import sys
and sys.modules.keys()
, you can see these modules as X
and X.Y
. And you can access the attributes in Y
by sys.modules["X.Y"].a # suppose there is
. That means the __init__.py
file under directory Y
has been executed.
OK, so now if importing Y
or X
will also execute all files under that package, guess what? Yes, even though you just need anotherFile
module, all files including directory Y
under directory X
will be executed. And these files also import other files and so on... With just one import, the whole project is imported.