四、元路径查找器(meta path finder)元路径查找器的工作就是看是否能找到模块 。这些查找器存放在 sys.meta_path 中以供 Python 遍历(当然它们也可以通过 import 勾子返回 , 参见上面的例子) 。每个查找器必须实现 find_spec 方法 。如果一个查找器知道怎么处理将引入的模块 , find_spec 将返回一个 ModuleSpec 对象(参见下节)否则返回 None 。
和之前提到的一样 sys.meta_path 包含三种查找器:
- 内置模块查找器
- 冻结模块查找器
- 基于路径的查找器
路径查找器不仅限于文件系统中的文件 , 它还可以上 URL 数据库的查询 , 或者其他任何可以用字符串表示的地址 。
你可以用上节提供的勾子来实现对同类型地址的模块查找 。例如 , 如果你想通过 URL 来 import 模块 , 那么你可以写一个 import 勾子来解析这个 URL 并且返回一个路径查找器 。
注意 , 路径查找器不同于元路径查找器 。后者在 sys.meta_path 中用于被 Python 遍历 , 而前者特指基于路径的查找器 。
五、ModuleSpec 对象每个元路径查找器必须实现 find_spec 方法 , 如果该查找器知道如果处理要引入的模块 , 那么这个方法将返回一个 ModuleSpec 对象 。这个对象有两个属性值得一提 , 一个是模块的名字 , 而另一个则是查找器 。如果一个 ModuleSpec 对象的查找器是 None , 那么类似 ImportError: missing loader 的异常将会被抛出 。查找器将用来创建和执行一个模块(见下节) 。
你可以通过 <module>.__spec__ 来查找模块的 ModuleSpec 对象:
In [1]: import sysIn [2]: sys.__spec__Out[2]: ModuleSpec(name='sys', loader=<class '_frozen_importlib.BuiltinImporter'>)
六、加载器(loader)加载器通过 create_module 来创建模块以及 exec_module 来执行模块 。通常如果一个模块是一个 Python 模块(非内置模块或者动态扩展) , 那么该模块的代码需要在模块的 __dict__ 空间上执行 。如果模块的代码无法执行 , 那么就会抛出ImportError 异常 , 或者其他在执行过程中的异常也会被抛出 。绝大多数情况下 , 查找器和加载器是同一个东西 。这种情况下 , 查找器的 find_spec 方法返回的 ModuleSpec 对象的 loader 属性将指向它自己 。
我们可以用 create_module 来动态创建一个模块 , 如果它返回 None Python 会自动创建一个模块 。
七、总结Python 的 import 机制灵活而强大 。以上的介绍大部分是基于官方文档 , 以及较新的 Python 3.6+ 版本 。由于篇幅 , 还有很多细节并没有包含其中 , 例如子模块的加载、模块代码的缓存机制等等 。文章中也难免出现纰漏如果有任何问题 , 欢迎到开 issue 提问及讨论 。
推荐阅读
- PLC的基本知识?plc的一些基础知识点
- 修复Windows 10更新错误的最佳方法
- 基于SpringBoot的微服务架构与K8S容器部署实践
- 防火墙基础与配置
- 萧何在汉书中属于 成也萧何败也萧何指的是西汉哪位开国功臣
- 朱元璋的郭宁莲是怎么死的 朱元璋老婆郭宁莲
- 哈尔科夫反击战的精妙之处
- 陈平和张良谁更会用计 陈平和张良谁的水平高
- 盗墓笔记里的汪家人是什么来历 盗墓笔记里的汪家人到底是什么人啊
- 这可能是网上最全的 Docker 工具集合