python - 为什么 Python 导入会隐式执行父模块?
问题描述
正如Python 文档所述,模块导入(以及从模块导入)总是在执行可能的父模块。例如,这些构成常规包的文件:
a_package/
__init__.py
a_submodule.py
a_submodule
从完全不同的包中导入,例如
from a_package.a_submodule import an_object
将首先执行a_package/__init__.py
,然后再执行a_package/a_submodule.py
并最终绑定an_object
到声明导入的命名空间。
我想知道这背后的设计原理或技术必要性是什么。特别是因为这对我来说似乎违反直觉,因为通常的包机制是一个有序图,其中父模块取决于其子包中的内容,反之亦然。事实上,如果该 import 语句示例在 中进行了评估a_package/__init__.py
,它不会触发自身的执行。当然,因为这将是一个循环依赖,但它表明子模块不依赖于它们的父模块。
解决方案
有几个原因。从能力的角度来看,最重要的是,包可以使用诸如__path__
帮助查找其子模块之类的机制,如果在继续导入子模块之前未对其进行配置,这显然将不起作用。另一个是方便:如果一个包在使用它的模块之前需要初始化,它可以被放入__init__.py
而不是让每个模块都需要from . import startup
。
此外,应该在什么时候初始化包?等到所有子模块都被导入是没有意义的,因为这可能永远不会发生;虽然它可能是“在子模块的第一次导入完成之后”,但仍然是在其他子模块的导入之前,并且会不一致和任意。特别是,没有模块可以使用其父级的内容,__init__.py
以防它是其兄弟姐妹中第一个被导入的。
至于循环依赖,Python 一直支持这些(至少对于绝对导入):导入一个已经被导入的模块只会产生一个对模块对象的引用(处于其部分形成的状态)。的行为from . import foo
(顺便说一句,作为执行的一部分通常是一个坏主意__init__.py
)也不例外。由于“额外导入”只是sys.modules
无论如何,它根本没有效果。
推荐阅读
- odbc - 使用 ODBC 查询获取 Netsuite Invoice 所有类型的行项目
- python-3.x - sqlalchemy 中的外键设置
- javascript - 我如何在反应中收听发布到 webhook 的数据?
- reactjs - 如何清除自动完成值
- c# - C# 中的合并排序实现 - StackOverflow 异常
- c# - 如何确定 Azure Blob 存储容器访问的 SAS 令牌是否已过期?
- linux - 如何配置 Nginx 和 Adminer
- java - 如何在应用程序模式下将 java 参数传递给 Flink 作业工件
- c# - 将用户控件元素绑定到模型属性
- regex - 正则表达式组重排