已加载模块和已初始化模块之间有什么区别?

3
参考手册中指出:

完整的Python程序在一个最小初始化的环境中执行:所有内置和标准模块都可用,但没有被初始化,除了sys(各种系统服务)、builtins(内置函数、异常和None)和__main__

我不确定这里的“初始化”应该是什么意思。之前我总是认为如果一个模块已经加载并存在于sys.modules中,则该模块已被初始化:

这是一个将模块名称映射到已加载的模块的字典。

显然,我错了,因为sys.modules包含许多其他模块:
python -c "import sys; print(sys.modules.keys() - {'sys', 'builtins', '__main__'})"
{'_stat', 'encodings.aliases', '_sitebuiltins', '_thread', 'io', '_weakrefset', 'genericpath', 'encodings.utf_8', 'codecs', 'os', '_weakref', '_codecs', '_frozen_importlib', '_io', '_frozen_importlib_external', 'os.path', '_warnings', '_bootlocale', '_signal', 'errno', '_imp', 'encodings.latin_1', 'sysconfig', 'marshal', 'encodings', 'usercustomize', 'site', 'posixpath', '_collections_abc', 'posix', '_sysconfigdata_m_linux_x86_64-linux-gnu', 'encodings.cp437', 'abc', 'zipimport', 'stat', '_locale'}

初始化模块和加载模块有什么区别?我使用的是Python 3。

2个回答

4

自从那份文档编写以来,语言初始化变得更加复杂。(至少从Python 1.4开始至今基本没有变化。)所有在sys.modules中的模块都已被完全加载和初始化。


看起来是这样,相当奇怪它没有得到任何关注,考虑到它在文档中明确与import相关联,特别是对于module.__spec__,而该文档最近已经更新。 - Bob Holver
能否详细解释一下问题中“已初始化模块”和“已加载模块”的区别?据我所知,已初始化的模块已经执行了其语句,而已加载的模块仅在符号表中可用。 - Alex
1
@Alex:导入系统参考将加载过程描述为包含初始化,以使“已加载”和“已初始化”等效。但我不会期望Python文档完全一致;这些术语,特别是“已加载”,应根据上下文来确定文档的意图。例如,sys.modules包含尚未按照导入系统文档中使用该术语的意义完全加载的模块。 - user2357112
啊,我明白了... 还有一句相关的引用来自这些文档:"当一个模块被首次导入时,Python会搜索该模块,如果找到,它会创建一个模块对象并初始化。" - Alex

-1
简单来说: import会将模块加载到内存中。
当你调用该模块中的类并使用 .__init__() 函数来更新属于该模块的某些属性时,则该模块就成为了已初始化的模块。
请注意,当您使用该模块时,此过程会隐式发生。
TL;DR import some_module 会加载该模块, some_module.some_attribute/function 则是在对其进行初始化。

这没什么意义。如果模块没有类,那么它就永远不会被初始化吗?我担心没有源代码这只是你对使用非常特定原因的单词的解释。 - Bob Holver
每个模块都有一个内置类。为了证明这一点,请尝试dir(module),你总会得到一个字典。嗯,'loaded'和'initialized'没有官方定义,只是行话。 - Harshith Thota
你所说的是模块内部的类,而不是模块对象。即使你在谈论模块对象,sys.modules 中的模块都已经初始化了,但这并没有在参考手册中说明。参考手册中明确提到了 sysbuiltins__main__ - Bob Holver
模块对象是模块内父类的一个实例。与用户创建的模块不同,这个类没有明确的定义,但这就是Python基于OOPS哲学使用类和对象的方式获得对象的方法。根据模块的不同,您可以将整个模块称为一个类,因为如果只有一个类,它自动成为父类。至于其他部分,当您运行脚本时,这三个部分会自动加载和初始化。 - Harshith Thota

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