Python将importlib做为标准库提供。它旨在提供Pythonimport语法和(__import__()函数)的实现。另外,importlib提供了开发者能够建立本身的对象(即importer)来处理导入过程。html
那么imp呢?还有一个imp模块提供了import语句接口,不过这个模块在Python3.4已经deprecated了。建议使用importlib来处理。python
这个模块比较复杂,文中咱们主要探讨以下主题:函数
- 动态导入
- 检查模块是否能够导入
- 从源文件导入
咱们先从动态导入开始。post
动态导入
importlib模块支持传递字符串来导入模块。咱们先来建立一些简单模块一遍演示。咱们在模块里提供了相同接口,经过打印它们自身名字来区分。咱们分别建立了foo.py和bar.py,代码以下:学习
def main():
print(__name__)
如今咱们尽须要使用importlib导入它们。咱们来看看代码是如何实现的,确保该代码在刚才建立的两个文件的相同目录下。url
#importer
import importlib def dynamic_import(module): return importlib.import_module(module) if __name__ == "__main__": module = dynamic_import('foo') module.main() module2 = dynamic_import('bar') module2.main()
这里咱们导入importlib模块,并建立了一个很是简单的函数dynamic_import。这个函数直接就调用了importlib的import_module方法,并将要导入的模块字符串传递做为参数,最后返回其结果。而后在主入口中咱们分别调用了各自的main方法,将打印出各自的name.spa
$ python3 importer.py
foo
bar
也许你不多会代码这么作,不过在你须要试用字符串做为导入路径的话,那么importlib就有用途了。orm
模块导入检查
Python有个众所周知的代码风格EAFP: Easier to ask forgiveness than permission.它所表明的意思就是老是先确保事物存在(例如字典中的键)以及在犯错时捕获。若是咱们在导入前想检查是否这个模块存在而不是靠猜。 使用mportlib就能实现。htm
import importlib.util def check_module(module_name): """ Checks if module can be imported without actually importing it """ 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): """ Import the module via the passed in module specification Returns the newly imported module """ 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。check_module里面调用find_spec方法, 传递该模块字符串做为参数。当咱们分别传入了一个不存在和存在的Python模块。你能够看到当你传入不存在的模块时,find_spec函数将返回 None,在咱们代码里就会打印提示。若是存在咱们将返回模块的specification。对象
咱们能够经过该模块的specification来实际导入该模块。或者你直接将字符串做为参数调用import_module函数。不过我这里也学习如何试用模块specification方式导入。看看import_module_from_spec函数。它接受check_module提供的模块specification做为参数。而后咱们将它传递给了module_from_spec函数,它将返回导入模块。Python文档推荐导入后而后执行模块,因此接下来咱们试用exec_module函数执行。最后咱们使用dir来确保获得预期模块。
从源代码导入
importlib的子模块有个很好用的技巧我想提提。你可使用util经过模块的名字和路径来导入模块。
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 logging import_source(logging)
在上面的代码中,咱们实际导入logging模块,并将模块传递给了import_source函数。这样咱们就能够经过导入的模块获取到实际的路 径和名字。而后咱们将信息传递给sec_from_file_location函数,它将返回模块的specification。也了这个咱们就能够在前 面那样直接经过importlib导入了。
总结
目前,你知道如何在代码中使用importlib和import钩子。这个模块内容很是多,若是你想自定义importer或者loader,那么你能够经过官方文档或者源代码了解更多。