Reputation: 431
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
~/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?
Upvotes: 5
Views: 2790
Reputation: 2819
Module a.c has no dependencies on module a
You are confusing a package with a module.
`a` is a package
`c` is a module within package `a`
There is a dependency: a.c
is a member of package a
.
Questions about this are common
What's the difference between a Python module and a Python package?
So, why does Python run module a as if it were importing it? To me this is surprising behavior
When you import module a.c
, python processes package a
which includes executing code in the a/__init__.py
and then module c.py
Q: Why?
A: Because that is what the language states it will do. :) (I know, that isn't really the why you meant.)
Q: Why? As in, "why would it do that, what good can that be?"
A: The package level init might do something useful.
The package init can provide things, and the members can count on the package being execute before the member module starts.
You put c
into package a
for a reason.
People can use packages simply for structural organization. If you have Java experience you may see the dots as just how you organize classes. If you are only using the a
for this reason, leave the __init__.py
empty and all will be as you expect.
But the package a/__init__.py
allows other abilities. It does require a care to use correctly, but is available when you need it.
Wouldn't this be dangerous for the scripts that don't use the protection of
if __name__ == "__main__":
?
Yes, you need to clearly know what are scripts meant to be run (for example python b.py
) and what are modules meant as containers for classes and functions.
In general, modules are not mean to be executed as stand alone scripts. The common exception is during test and development. Then you will regularly see bits of test code
if __name__ == "__main__":
x = somefunction()
print(x)
a = SomeClass()
y = a.foo()
print(y)
Upvotes: 1
Reputation: 44444
Module a.c has no dependencies on module a. So, why does Python run module a as if it were importing it
Importing parent.one will implicitly execute
parent/__init__.py
andparent/one/__init__.py
. Subsequent imports ofparent.two
orparent.three
will executeparent/two/__init__.py
andparent/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.
Upvotes: 2