Python importlib讲解
Python标准库中提供了importlib模块,目的是提供import语句(还有import())的底层实现,另外,importlib让程序员可以在导入过程中创建自己的对象。之前的imp模块在Python3.4中被importlib取代了。
importlib模块非常复杂,下面只讲解其中的一部分内容。
动态导入
importlib支持通过字符串动态导入模块,如:
1 2 3 4 5
| imoprt importlib foo = importlib.import_module('foo') foo.main()
|
模块导入检查
导入模块当模块不存在时会抛出ImportError异常,如果我们想在导入模块之前检查该模块是否可以被导入,可以使用importlib模块进行检查,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import importlib.util def check_module(module_name): """检查模块时候能被导入而不用实际的导入模块""" module_spec = importlib.util.find_spec(module_name) if module_spec is None: print('Module: {} not found'.format(module_name)) return None else: print('Module: {} can be imported!'.format(module_name)) return module_spec def import_module_from_spec(module_spec): """通过传入模块的spec返回新的被导入的模块对象""" module = importlib.util.module_from_spec(module_spec) module_spec.loader.exec_module(module) return module if __name__ == '__main__': module_spec = check_module('fake_module') module_spec = check_module('collections') if module_spec: module = import_module_from_spec(module_spec) print(dir(module))
|
从源文件中导入
importlib.util工具还有一个功能,可以在仅仅知道模块名字和路径的情况下通过该工具导入,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import importlib.util def import_source(module_name): module_file_path = module_name.__file__ module_name = module_name.__name__ module_spec = importlib.util.spec_from_file_location(module_name, module_file_path) module = importlib.util.module_from_spec(module_spec) module_spec.loader.exec_module(module) print(dir(module)) msg = 'The {module_name} module has the following methods: {methods}' print(msg.format(module_name=module_name, methods=dir(module))) if __name__ == '__main__': import os import_source(os)
|
import_from_github_com
有一个优雅的模块import_from_github_com可以从github中寻找并加载模块,该模块使用了PEP 302中提供的import hook来实现功能。该模块并没有使用importlib模块,而是使用pip安装模块,如果pip没有安装则使用Python的import()函数实际导入新的安装模块。
参考:《Python 201》第五章