假设以下代码结构:
#### 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
我在python
内运行1/
并执行import hhh.foo.baz
。它失败了:
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'
现在我将baz.py
替换为:
# 1/hhh/foo/baz.py:
from hhh.foo.bar import xyzzy
qux = xyzzy + 10
再次执行import hhh.foo.baz
。现在它可以工作,虽然我正在加载相同的模块,只绑定一个不同的名称。
这是否意味着import module
和from module import name
之间的区别超出了标识符?到底发生了什么?
(我知道我可以使用相对导入来解决所有这些问题,但我仍然想了解其中的机制。另外,我不喜欢相对导入,PEP 8也不喜欢。)
答案 0 :(得分:8)
当您编写from hhh.foo.bar import xyzzy
时,Python解释器将尝试从模块xyzzy
加载hhh.foo.bar
。但是如果你写import hhh.foo.bar as bar
,它会先尝试在bar
模块中找到hhh.foo
。所以它评估hhh.foo
,做from hhh.foo.baz import *
。 hhh.foo.baz
尝试评估hhh.foo
,hhh.foo
尝试评估hhh.foo.baz
,循环导入,例外。
答案 1 :(得分:0)
1/hhh/foo/__init__.py
中您需要设置__all__
列表,其中包含您要导出的名称。即__all__ = ["xyzzy"]
答案 2 :(得分:0)
为什么要从hhh.foo中的hhh.foo.bar导入? import bar
就足够了。