Assume the following code structure:
#### 1/hhh/__init__.py: empty
#### 1/hhh/foo/__init__.py:
from hhh.foo.baz import *
#### 1/hhh/foo/bar.py:
xyzzy = 4
#### 1/hhh/foo/baz.py:
import hhh.foo.bar as bar
qux = bar.xyzzy + 10
I run python
inside 1/
and do import hhh.foo.baz
. It fails:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "hhh/foo/__init__.py", line 1, in <module>
from hhh.foo.baz import *
File "hhh/foo/baz.py", line 1, in <module>
import hhh.foo.bar as bar
AttributeError: 'module' object has no attribute 'foo'
Now I replace baz.py
with:
# 1/hhh/foo/baz.py:
from hhh.foo.bar import xyzzy
qux = xyzzy + 10
and again do import hhh.foo.baz
. Now it works, although I’m loading the same module, only binding a different name.
Does this mean that the distinction between import module
and from module import name
goes beyond just identifiers? What exactly is going on here?
(I know I can use relative imports to work around all this, but still I’d like to understand the mechanics. Plus I don’t like relative imports, and neither does PEP 8.)
When you write from hhh.foo.bar import xyzzy
Python interpreter will try to load xyzzy
from module hhh.foo.bar
. But if you write import hhh.foo.bar as bar
it will try first to find bar
in hhh.foo
module. So it evaluates hhh.foo
, doing from hhh.foo.baz import *
. hhh.foo.baz
tries to evaluate hhh.foo
, hhh.foo
tries to evaluate hhh.foo.baz
, cyclic imports, exception.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With