为什么这两个Python导入方式表现不同?

7
假设有如下代码结构:
#### 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 modulefrom module import name 之间的区别超出了仅仅是标识符?这里到底发生了什么?

(我知道我可以使用相对导入来解决所有这些问题,但我仍然想了解其中的机制。此外,我不喜欢相对导入,PEP8也不喜欢。)

3个回答

8
当你写下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.foohhh.foo尝试评估hhh.foo.baz,循环导入,异常。

0
1/hhh/foo/__init__.py 中,您需要设置 __all__ 列表,其中包含您要导出的名称。例如:__all__ = ["xyzzy"]

0
为什么在hhh.foo中从hhh.foo.bar导入?import bar就足够了。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接