5.3.4. 元路径
当指定名称的模块在 sys.modules
中找不到时,Python 会接着搜索 sys.meta_path
,其中包含元路径查找器对象列表。 这些查找器按顺序被查询以确定它们是否知道如何处理该名称的模块。 元路径查找器必须实现名为 find_spec()
的方法,该方法接受三个参数:名称、导入路径和目标模块(可选)。 元路径查找器可使用任何策略来确定它是否能处理指定名称的模块。
如果元路径查找器知道如何处理指定名称的模块,它将返回一个说明对象。 如果它不能处理该名称的模块,则会返回 None
。 如果 sys.meta_path
处理过程到达列表末尾仍未返回说明对象,则将引发 ModuleNotFoundError
。 任何其他被引发异常将直接向上传播,并放弃导入过程。
元路径查找器的 find_spec()
方法调用带有两到三个参数。 第一个是被导入模块的完整限定名称,例如 foo.bar.baz
。 第二个参数是供模块搜索使用的路径条目。 对于最高层级模块,第二个参数为 None
,但对于子模块或子包,第二个参数为父包 __path__
属性的值。 如果相应的 __path__
属性无法访问,将引发 ModuleNotFoundError
。 第三个参数是一个将被作为稍后加载目标的现有模块对象。 导入系统仅会在重加载期间传入一个目标模块。
对于单个导入请求可以多次遍历元路径。 例如,假设所涉及的模块都尚未被缓存,则导入 foo.bar.baz
将首先执行顶级的导入,在每个元路径查找器 (mpf
) 上调用 mpf.find_spec("foo", None, None)
。 在导入 foo
之后,foo.bar
将通过第二次遍历元路径来导入,调用 mpf.find_spec("foo.bar", foo.__path__, None)
。 一旦 foo.bar
完成导入,最后一次遍历将调用 mpf.find_spec("foo.bar.baz", foo.bar.__path__, None)
。
有些元路径查找器只支持顶级导入。 当把 None
以外的对象作为第三个参数传入时,这些导入器将总是返回 None
。
Python 的默认 sys.meta_path
具有三种元路径查找器,一种知道如何导入内置模块,一种知道如何导入冻结模块,还有一种知道如何导入来自 import path 的模块 (即 path based finder)。
在 3.4 版更改: 元路径查找器的 find_spec()
方法替代了 find_module()
,后者现已弃用,它将继续可用但不会再做改变,导入机制仅会在查找器未实现 find_spec()
时尝试使用它。