为什么这两个Python导入的工作方式不同?

时间:2011-07-18 09:02:45

标签: python import module package

假设以下代码结构:

#### 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 modulefrom module import name之间的区别超出了标识符?到底发生了什么?

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

3 个答案:

答案 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.foohhh.foo尝试评估hhh.foo.baz,循环导入,例外。

答案 1 :(得分:0)

1/hhh/foo/__init__.py

您需要设置__all__列表,其中包含您要导出的名称。即__all__ = ["xyzzy"]

答案 2 :(得分:0)

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