20.2. importlib — python 的模块载入机制 | 模块和扩展 |《python 3 标准库实例教程》| python 技术论坛-金年会app官方网

未匹配的标注

目的: importlib 模块公开了 python 中 import 语句的实现

importlib 模块包含实现 python 导入机制的函数,用于在包和模块中加载代码。 它是动态导入模块的一个访问点,在编写代码时需要导入的模块名称未知的情况下很有用(例如,对于应用程序的插件或扩展)。

示例包

本节的示例使用了一个包
称为 example ,包含有  __init__.py

example/init.py

print('importing example package')

这个包还包含 submodule.py

example/submodule.py

print('importing submodule')

导入包或模块时,请注意示例中 print() 调用输出的文本。

模块类型

python 支持多种样式的模块。 打开模块并将其添加到命名空间时,每个模块都需要自己处理,并且格式的支持因平台而异。 例如,在 microsoft windows 下,共享库是从扩展名为 .dll.pyd 的文件加载而不是 .so 。 当使用解释器的调试版本而不是正常版本构建时,c 模块的扩展也可能会发生变化,因为它们也可以进行包含的调试信息编译。如果 c 扩展库或其他模块未按预期加载,请使用 importlib.machinery 中定义的常量来查找当前平台支持的类型以及加载它们的参数。

importlib_suffixes.py

import importlib.machinery
suffixes = [
    ('source:', importlib.machinery.source_suffixes),
    ('debug:',
     importlib.machinery.debug_bytecode_suffixes),
    ('optimized:',
     importlib.machinery.optimized_bytecode_suffixes),
    ('bytecode:', importlib.machinery.bytecode_suffixes),
    ('extension:', importlib.machinery.extension_suffixes),
]
def main():
    tmpl = '{:<10}  {}'
    for name, value in suffixes:
        print(tmpl.format(name, value))
if __name__ == '__main__':
    main()

返回值是包含文件扩展名的元组序列,用于打开包含模块的文件的模式,以及来自模块中定义的常量的类型代码。 此表是不完整的,因为某些可导入的模块或包类型不对应到单个文件。

$ python3 importlib_suffixes.py
source:     ['.py']
debug:      ['.pyc']
optimized:  ['.pyc']
bytecode:   ['.pyc']
extension:  ['.cpython-36m-darwin.so', '.abi3.so', '.so']

导入模块

importlib 中的高级 api 使得在给定绝对或相对名称的情况下导入模块变得简单。 使用相对模块名称时,将包含模块的包指定为单独的参数。

importlib_import_module.py

import importlib
m1 = importlib.import_module('example.submodule')
print(m1)
m2 = importlib.import_module('.submodule', package='example')
print(m2)
print(m1 is m2)

import_module() 的返回值是导入创建的模块对象。

$ python3 importlib_import_module.py
importing example package
importing submodule


true

如果模块不能被导入 import_module() 将引发 importerror 错误。

importlib_import_module_error.py

import importlib
try:
    importlib.import_module('example.nosuchmodule')
except importerror as err:
    print('error:', err)

错误消息包含缺少的模块的名称。

$ python3 importlib_import_module_error.py
importing example package
error: no module named 'example.nosuchmodule'

要重新载入已有模块,使用 reload()

importlib_reload.py

import importlib
m1 = importlib.import_module('example.submodule')
print(m1)
m2 = importlib.reload(m1)
print(m1 is m2)

reload() 的返回值是新模块。 根据使用的加载器类型不同,它可能是相同的模块实例。

$ python3 importlib_reload.py
importing example package
importing submodule

importing submodule
true

加载器

importlib 中的低级 api 提供对 loader 对象的访问,如中 sys 模块一节所述。 要获取模块的加载器,请使用 find_loader() 。 然后获取模块,使用 loader 的 load_module() 方法。

importlib_find_loader.py

import importlib
loader = importlib.find_loader('example')
print('loader:', loader)
m = loader.load_module()
print('module:', m)

这个示例加载了 example 包的顶层。

$ python3 importlib_find_loader.py
loader: <_frozen_importlib_external.sourcefileloader object at
0x101fe1828>
importing example package
module: 

包中的子模块需要使用包中的路径单独加载。 在下面的示例中,首先加载包,然后将其路径传递给 find_loader() 以创建能够加载子模块的加载器。

importlib_submodule.py

import importlib
pkg_loader = importlib.find_loader('example')
pkg = pkg_loader.load_module()
loader = importlib.find_loader('submodule', pkg.__path__)
print('loader:', loader)
m = loader.load_module()
print('module:', m)

import_module() 不同,子模块的名称应该没有任何相对路径前缀,因为加载器已经受到包路径的约束。

$ python3 importlib_submodule.py
importing example package
loader: <_frozen_importlib_external.sourcefileloader object at
0x101fe1f28>
importing submodule
module: 

参见

  •  -- 导入钩子,模块搜索路径以及 sys 模块中的其他相关机器。
  •  -- 以编程方式从模块加载信息。
  •  -- 新的 import 钩子。
  •  -- 过去的 import 钩子。
  •  -- 消除pyo文件。

本文章首发在 金年会app官方网 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 cc 协议,如果我们的工作有侵犯到您的权益,请及时联系金年会app官方网。

原文地址:https://learnku.com/docs/pymotw/importli...

译文地址:https://learnku.com/docs/pymotw/importli...

上一篇 下一篇
讨论数量: 0



暂无话题~
网站地图