来自<module> import ... in __init__.py使模块名称可见?

yol*_*ole 15 python python-import

请使用以下代码示例:

档案package1/__init__.py:

from moduleB import foo
print moduleB.__name__
Run Code Online (Sandbox Code Playgroud)

档案package1/moduleB.py:

def foo(): pass
Run Code Online (Sandbox Code Playgroud)

然后从当前目录:

>>> import package1
package1.moduleB
Run Code Online (Sandbox Code Playgroud)

此代码适用于CPython.令我惊讶的是,from ... importin __init__.py语句使moduleB名称可见.根据Python文档,情况不应该是这样的:

from表单不绑定模块名称

有人可以解释为什么CPython这样工作吗?有没有详细描述这个的文件?

Fre*_*urk 6

文档误导了您,因为它是为了描述从包含它的父包外部导入模块的更常见情况.

例如,在我自己的代码中使用"from example import submodule",其中"example"是一些完全未连接到我自己的代码的第三方库,不绑定名称"example".但是它仍然导入二者的例子/ __ init__.py和实例/ submodule.py模块,创建两个模块对象,并分配example.submodule到第二模块的对象.

但是,来自子模块的名称"from..import"必须在父包对象上设置子模块属性.考虑一下是否:

  1. 导入包时执行package/__ init__.py.

  2. 那个__init__"来自子模块导入名称".

  3. 稍后,其他完全不同的代码会"导入package.submodule".

在步骤3中,无论sys.modules中["package.submodule"]不存在,在这种情况下,再次加载它给你两个不同在不同的范围模块对象; 或sys.modules ["package.submodule"]将存在,但"submodule"将不是父包对象的属性(sys.modules ["package"]),"import package.submodule"将不执行任何操作.但是,如果它什么也不做,使用导入的代码无法访问子模块作为包的属性!


从理论上讲,如果导入机器的其余部分已更改为匹配,则可以更改导入子模块的方式.

如果你只需要知道从包P中导入一个子模块S会做什么,那么简而言之:

  1. 确保导入P,否则导入P. (此步骤递归处理"导入ABCD".)
  2. 执行S.py以获取模块对象.(跳过.pyc文件的详细信息等)
  3. 将模块对象存储在sys.modules ["PS"]中.
  4. setattr(sys.modules["P"], "S", sys.modules["P.S"])
  5. 如果导入的格式为"import PS",则在本地范围内绑定"P".