5.4.1. 加载器
模块加载器提供关键的加载功能:模块执行。 导入机制调用 importlib.abc.Loader.exec_module()
方法并传入一个参数来执行模块对象。 从 exec_module()
返回的任何值都将被忽略。
加载器必须满足下列要求:
如果模块是一个 Python 模块(而非内置模块或动态加载的扩展),加载器应该在模块的全局命名空间 (
module.__dict__
) 中执行模块的代码。如果加载器无法执行指定模块,它应该引发
ImportError
,不过在exec_module()
期间引发的任何其他异常也会被传播。
在许多情况下,查找器和加载器可以是同一对象;在此情况下 find_spec()
方法将返回一个规格说明,其中加载器会被设为 self
。
模块加载器可以选择通过实现 create_module()
方法在加载期间创建模块对象。 它接受一个参数,即模块规格说明,并返回新的模块对象供加载期间使用。 create_module()
不需要在模块对象上设置任何属性。 如果模块返回 None
,导入机制将自行创建新模块。
3.4 新版功能: 加载器的 create_module()
方法。
在 3.4 版更改: load_module()
方法被 exec_module()
所替代,导入机制会对加载的所有样板责任作出假定。
为了与现有的加载器兼容,导入机制会使用导入器的 load_module()
方法,如果它存在且导入器也未实现 exec_module()
。 但是,load_module()
现已弃用,加载器应该转而实现 exec_module()
。
除了执行模块之外,load_module()
方法必须实现上文描述的所有样板加载功能。 所有相同的限制仍然适用,并带有一些附加规定:
如果
sys.modules
中存在指定名称的模块对象,加载器必须使用已存在的模块。 (否则importlib.reload()
将无法正确工作。) 如果该名称模块不存在于sys.modules
中,加载器必须创建一个新的模块对象并将其加入sys.modules
。在加载器执行模块代码之前,模块 必须 存在于
sys.modules
之中,以防止无限递归或多次加载。如果加载失败,加载器必须移除任何它已加入到
sys.modules
中的模块,但它必须 仅限 移除加载失败的模块,且所移除的模块应为加载器自身显式加载的。
在 3.5 版更改: 当 exec_module()
已定义但 create_module()
未定义时将引发 DeprecationWarning
。
在 3.6 版更改: 当 exec_module()
已定义但 create_module()
未定义时将引发 ImportError
。