Andrew McKinlay Andrew McKinlay - 5 months ago 12
Python Question

Why does running a submodule (python -m a.c) also import the containing module?

Given:

tree



~/dir
▶ tree
.
├── a
│   ├── __init__.py
│   ├── c.py
└── b.py

1 directory, 3 files


*.py
files



~/dir
▶ tail -n +1 **/*.py
==> a/__init__.py <==
print(__name__)
import a.c

==> a/c.py <==
print(__name__)

==> b.py <==
print(__name__)
import a


I/O



~/dir
▶ python3 -m a.c
a
a.c
__main__


Module
a.c
has no dependencies on module
a
. So, why does Python run module
a
as if it were importing it? To me this is surprising behavior. I didn't expect running a script without imports would cause the script itself to be imported and evaluated twice. Wouldn't this be dangerous for the scripts that don't use the protection of
if __name__ == "__main__"
?

What is the justification for this behavior? Why does Python need to evaluate the containing module upon running its submodule?

Answer

Module a.c has no dependencies on module a. So, why does Python run module a as if it were importing it

From the documentation:

Importing parent.one will implicitly execute parent/__init__.py and parent/one/__init__.py. Subsequent imports of parent.two or parent.three will execute parent/two/__init__.py and parent/three/__init__.py respectively.


To me this is surprising behavior. I didn't expect running a script without imports would cause the script itself to be imported and evaluated twice.

No, this isn't suprising. Think about this: whatever objects are exposed by package a in your example is controlled by a/__init__.py. The interpreter now has to evaluate a/__init__.py to find out if a.c exists at all. And in the process, the print statement is executed. Further, no module is imported twice. It is imported only once -- although you could technically write import statements multiple times.

Comments