为什么这两个 Python 导入的工作方式不同?
假设以下代码结构:
#### 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
我在 1/
内运行 python
并执行 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 也不喜欢。)
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.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为什么要从 hhh.foo.bar 导入 hhh.foo?
import bar
应该足够了。Why do you import from hhh.foo.bar in hhh.foo?
import bar
should suffice there.在
1/hhh/foo/__init__.py
中,您需要使用要导出的名称设置__all__
列表。即__all__ = ["xyzzy"]
in
1/hhh/foo/__init__.py
you need to set the__all__
list with the names of what you want to export. i.e.__all__ = ["xyzzy"]
当您编写
from hhh.foo.bar import xyzzy
时,Python 解释器将尝试从模块hhh.foo.bar
加载xyzzy
。但是,如果您编写import hhh.foo.bar as bar
,它会首先尝试在hhh.foo
模块中查找bar
。因此它评估hhh.foo
,执行from hhh.foo.baz import *
。hhh.foo.baz
尝试评估hhh.foo
,hhh.foo
尝试评估hhh.foo.baz
>,循环导入,例外。When you write
from hhh.foo.bar import xyzzy
Python interpreter will try to loadxyzzy
from modulehhh.foo.bar
. But if you writeimport hhh.foo.bar as bar
it will try first to findbar
inhhh.foo
module. So it evaluateshhh.foo
, doingfrom hhh.foo.baz import *
.hhh.foo.baz
tries to evaluatehhh.foo
,hhh.foo
tries to evaluatehhh.foo.baz
, cyclic imports, exception.