# 31.5. `importlib` —— `import` 的实现

版本3.1中的新功能。

源代码： Lib/importlib/__init__.py

## 31.5.1. 引言

`importlib` 包有两种目的。一是提供Python源代码中`import`语句（和扩展，如 `__import__()` 函数）的实现。这里提供的 `import` 的实现可以移植到任何 Python 解释器。这里提供的实现比非 Python 编程语言的实现更容易理解。

二是实现`import`的组件在此包中公开，使用户更容易创建自己的自定义对象（通常称为importer）以参与导入过程。

另见

The import statement
  `import`语句的语言参考。
包规范
  包装的原始规格。自此文档编写以来，一些语义已发生变化（例如，基于`sys.modules`中`None`的重定向）。
`__import__()`函数
  `import`语句是该函数的语法糖。
PEP 235
  在不区分大小写的平台上导入
PEP 263
  定义Python源代码编码
PEP 302
  新的导入钩子
PEP 328
  进口：多线和绝对/相对
PEP 366
  主模块显式相对导入
PEP 420
  隐式名称空间包
PEP 451
  导入系统的ModuleSpec类型
PEP 488
  消除PYO文件
PEP 489
  多相扩展模块初始化
PEP 3120
  使用UTF-8作为默认源编码
PEP 3147
  PYC存储库目录

## 31.5.2. 函数

`importlib.``__import__`(name, globals=None, locals=None, fromlist=(), level=0)

  内置`__import__()`函数的实现。

  注意

  程序中的模块导入应该使用 `import_module()` 而不是这个函数。

`importlib.``import_module`(name, package=None)

  导入一个模块。name 参数指定要导入的模块，可以是绝对路径或相对路径（比如：`pkg.mod` 或 `..mod`）。如果 name 是以相对路径，则 package 参数必须设置为包的名称，该名称将作为解析包名称的锚点（比如：`import_module('..mod', 'pkg.subpkg')` 将导入 `pkg.mod`）。

  `import_module()` 函数是 `importlib.__import__()` 的简单化封装。这意味着该函数的所有语义都来自 `importlib.__import__()`。这两个函数最重要的区别在于 `import_module()` 返回指定的包或模块（例如，`pkg.mod`），而 `__import__()` 返回顶级的包或模块（例如，`pkg`）。

  如果你正在动态导入的模块是在解释器执行以后创建的（例如创建的 Python 源文件），则可能需要调用 `invalidate_caches()` 以使新模块被 import 系统觉察到。

  在版本3.3中更改：父包会自动导入。

`importlib.``find_loader`(name, path=None)

  查找模块的加载程序，可选地在指定的路径中。If the module is in `sys.modules`, then `sys.modules[name].__loader__` is returned (unless the loader would be `None` or is not set, in which case `ValueError` is raised). 否则，使用`sys.meta_path`完成搜索。`None` is returned if no loader is found.

  虚线名称没有父项的隐式导入，因为需要加载它们，这可能不是所期望的。要正确导入子模块，您需要导入子模块的所有父包，并将正确的参数用于路径。

  版本3.3中的新功能。

  在版本3.4中更改：如果未设置`__loader__`，则引发`ValueError`，就像属性设置为`None`

  从版本3.4开始弃用：改为使用`importlib.util.find_spec()`。

`importlib.``invalidate_caches`()

  使存储在`sys.meta_path`中的finders的内部缓存失效。如果查找程序实现`invalidate_caches()`，那么它将被调用来执行无效操作。如果在程序运行时创建/安装了任何模块以确保所有查找程序都会注意到新模块的存在，则应该调用此函数。

  版本3.3中的新功能。

`importlib.``reload`(module)

  重新载入先前导入的 module。参数必须是一个模块对象，因此必须先被成功导入。如果你使用外部编辑器编辑了模块源文件，并希望在不离开 Python 解释器的情况下尝试新版本，这将非常有用。返回值是模块对象（如果重新导入会导致将不同的对象放置在`sys.modules`中，则返回值可能不同）。

  当执行`reload()`时：

  - 重新编译Python模块的代码并重新执行模块级代码，通过重新使用最初加载模块的loader来定义一组新的对象，这些对象绑定到模块字典中的名称。扩展模块的 `init` 函数不再第二次调用。
  - 与Python中的所有其他对象一样，旧对象只有在引用计数下降到零后才被回收。
  - 模块命名空间中的名称将更新为指向任何新的或已更改的对象。
  - 对旧对象的其他引用（例如模块外部的名称）不会重新引用来引用新对象，如果需要，必须在每个命名空间中对其进行更新。

  还有一些其他警告：

  重新加载模块时，将保留其字典（包含模块的全局变量）。名称的重定义将覆盖旧的定义，因此这通常不是问题。如果模块的新版本未定义由旧版本定义的名称，则旧定义将保留。如果它维护一个全局表或对象缓存，使用`try`语句可以测试表的存在并跳过其初始化，如果需要，这个特性可以用于模块的优势：

      try:
          cache
      except NameError:
          cache = {}

  重新加载内置或动态加载的模块通常不是很有用。不推荐重新加载`sys`，`__main__`，`builtins`和其他关键模块。在许多情况下，扩展模块并不是设计成多次初始化的，并且在重新加载时可能会以任意方式失败。

  If a module imports objects from another module using `from` ... `import` ..., calling `reload()` for the other module does not redefine the objects imported from it — one way around this is to re-execute the `from` statement, another is to use `import` and qualified names (module.name) instead.

  如果一个模块实例化一个类的实例，重新加载定义该类的模块不会影响实例的方法定义 - 它们继续使用旧的类定义。对于派生类同样如此。

  版本3.4中的新功能。

## 31.5.3. `importlib.abc` - 与导入相关的抽象基类

源代码： Lib/importlib/abc.py

`importlib.abc`模块包含`import`使用的所有核心抽象基类。核心抽象基类的一些子类也被提供来帮助实现核心ABCs。

ABC层次结构：

    object
     +-- Finder (deprecated)
     |    +-- MetaPathFinder
     |    +-- PathEntryFinder
     +-- Loader
          +-- ResourceLoader --------+
          +-- InspectLoader          |
               +-- ExecutionLoader --+
                                     +-- FileLoader
                                     +-- SourceLoader

class `importlib.abc.``Finder`

  表示finder的抽象基类。

  从版本3.3开始弃用：改为使用`MetaPathFinder`或`PathEntryFinder`。

  abstractmethod `find_module`(fullname, path=None)

    用于查找指定模块的loader的抽象方法。该方法最初在 PEP 302中指定，用于`sys.meta_path`和基于路径的导入子系统中。

    在版本3.4中更改：调用时不返回`NotImplementedError`时返回`None`。

class `importlib.abc.``MetaPathFinder`

  表示meta path finder的抽象基类。为了兼容性，这是`Finder`的一个子类。

  版本3.3中的新功能。

  `find_spec`(fullname, path, target=None)

    为指定模块查找spec的抽象方法。如果这是顶级导入，则路径将为`None`。否则，这是对子包或模块的搜索，并且path将是父包中的`__path__`的值。如果找不到规格，则返回`None`。传入时，`target`是一个模块对象，取景器可以使用它来更好地了解要返回的规范。

    版本3.4中的新功能。

  `find_module`(fullname, path)

    用于查找指定模块的loader的传统方法。如果这是顶级导入，则路径将为`None`。否则，这是对子包或模块的搜索，并且path将是父包中的`__path__`的值。如果找不到加载程序，则返回`None`。

    如果定义了`find_spec()`，则提供了向后兼容的功能。

    在版本3.4中更改：调用时不返回`NotImplementedError`时返回`None`。可以使用`find_spec()`来提供功能。

    从版本3.4开始弃用：改为使用`find_spec()`。

  `invalidate_caches`()

    一个可选的方法，被调用时应该使查找器使用的任何内部缓存失效。当`sys.meta_path`中的所有查找器的缓存失效时，由`importlib.invalidate_caches()`使用。

    在版本3.4中更改：在调用而不是`NotImplemented`时返回`None`。

class `importlib.abc.``PathEntryFinder`

  表示path entry finder的抽象基类。虽然它与`MetaPathFinder`有一些相似之处，但`PathEntryFinder`仅适用于`PathFinder`提供的基于路径的导入子系统内。由于兼容性原因，此ABC是`Finder`的子类。

  版本3.3中的新功能。

  `find_spec`(fullname, target=None)

    为指定模块查找spec的抽象方法。取景器将只在分配给它的path entry内搜索模块。如果找不到规格，则返回`None`。传入时，`target`是一个模块对象，取景器可以使用它来更好地了解要返回的规范。

    版本3.4中的新功能。

  `find_loader`(fullname)

    用于查找指定模块的loader的传统方法。返回`（loader， 部分）的2元组，其中`portion`是一系列文件系统位置，命名空间包的一部分。`当指定`portion`来表示文件系统位置对名称空间包的贡献时，加载器可以是`None`。一个空的列表可以用于`portion`来表示加载器不是名称空间包的一部分。如果`loader`是`None`且`portion`是空列表，则不会找到名称空间包的加载器或位置。未能找到任何模块）。

    如果定义了`find_spec()`，则提供向后兼容的功能。

    版本3.4中改变：返回`（None， []）`，而不是引发`NotImplementedError` 在可用时使用`find_spec()`来提供功能。

    从版本3.4开始弃用：改为使用`find_spec()`。

  `find_module`(fullname)

    `Finder.find_module()`的具体实现等同于`self.find_loader(fullname)[0]`。

    从版本3.4开始弃用：改为使用`find_spec()`。

  `invalidate_caches`()

    一个可选的方法，被调用时应该使查找器使用的任何内部缓存失效。在使所有缓存查找器的缓存无效时，由`PathFinder.invalidate_caches()`使用。

class `importlib.abc.``Loader`

  一个loader。有关加载程序的确切定义，请参阅 PEP 302。

  `create_module`(spec)

    导入模块时返回要使用的模块对象的方法。此方法可能会返回`None`，表示应该发生默认的模块创建语义。

    版本3.4中的新功能。

    在版本3.5中更改：从Python 3.6开始，当定义`exec_module()`时，此方法将不可选。

  `exec_module`(module)

    抽象方法，用于在导入或重新加载模块时在其自己的名称空间中执行模块。当调用exec_module()时，模块应该已经被初始化。

    版本3.4中的新功能。

  `load_module`(fullname)

    加载模块的传统方法。如果模块无法加载，则引发`ImportError`，否则返回加载的模块。

    如果请求的模块已经存在于`sys.modules`中，则应该使用并重新加载该模块。否则，加载程序应该在任何加载开始之前创建一个新模块并将其插入到`sys.modules`中，以防止导入引发递归。如果加载程序插入了一个模块并且加载失败，则它必须由加载程序从`sys.modules`中删除。已经在`sys.modules`中的模块应该放在一起（参见`importlib.util.module_for_loader()`）。

    加载器应该在模块上设置几个属性。（请注意，某些模块重新加载时，这些属性可能会发生变化）：

    - `__name__`

        模块的名称。

    - `__file__`

        模块数据存储位置的路径（未为内置模块设置）。

    - `__cached__`

        应该存储模块的已编译版本的路径（当属性不合适时不会设置）。

    - `__path__`

        指定包内搜索路径的字符串列表。该属性未在模块上设置。

    - `__package__`

        模块/包的父包。如果模块是顶层的，那么它有一个空字符串的值。`importlib.util.module_for_loader()`修饰器可以处理`__package__`的细节。

    - `__loader__`

        加载器用于加载模块。`importlib.util.module_for_loader()`修饰器可以处理`__package__`的细节。

    当`exec_module()`可用时，提供向后兼容的功能。

    在版本3.4中更改：在调用`NotImplementedError`时调用`ImportError`。当`exec_module()`可用时提供的功能。

    从版本3.4开始不推荐使用：用于加载模块的推荐API是`exec_module()`（和`create_module()`）。加载器应该实现它而不是load_module()。当执行exec_module()时，导入机器负责load_module()的所有其他职责。

  `module_repr`(module)

    传统方法，在实现时计算并返回给定模块的repr，作为字符串。模块类型的默认repr()将根据需要使用此方法的结果。

    版本3.3中的新功能。

    在3.4版本中更改：制作可选，而不是抽象方法。

    从版本3.4开始不推荐使用：导入机器现在自动处理。

class `importlib.abc.``ResourceLoader`

  一个loader的抽象基类，它实现了用于从存储后端加载任意资源的可选的 PEP 302

  abstractmethod `get_data`(path)

    返回位于路径的数据的字节的抽象方法。具有允许存储任意数据的文件类存储后端的加载器可以实现这种抽象方法，以直接访问存储的数据。`OSError` is to be raised if the path cannot be found. 预计路径将使用模块的`__file__`属性或来自包的`__path__`的项目构建。

    版本3.4中改变：引发`OSError`而不是`NotImplementedError`。

class `importlib.abc.``InspectLoader`

  一个loader的抽象基类，它为检查模块的加载器实现可选的 PEP 302协议。

  `get_code`(fullname)

    返回模块的代码对象，如果模块没有代码对象，则返回`None`（例如，对于内置模块就是这种情况）。如果加载程序无法找到请求的模块，请引发`ImportError`。

    注意

    虽然该方法有一个默认的实现，但是如果可能的话，建议它被覆盖。

    在版本3.4中更改：不再提供抽象和具体实现。

  abstractmethod `get_source`(fullname)

    一种抽象方法来返回模块的来源。它使用universal newlines作为文本字符串返回，将所有已识别的行分隔符转换为`'\n'`个字符。如果没有可用的来源（例如，来源），则返回`None`。一个内置模块）。如果加载程序找不到指定的模块，则引发`ImportError`。

    在版本3.4中更改：引发`ImportError`而不是`NotImplementedError`。

  `is_package`(fullname)

    如果模块是包，则返回true值的抽象方法，否则返回false值。`ImportError` is raised if the loader cannot find the module.

    在版本3.4中更改：引发`ImportError`而不是`NotImplementedError`。

  static `source_to_code`(data, path='<string>')

    从Python源代码创建一个代码对象。

    data参数可以是`compile()`函数支持的任何内容（即，字符串或字节）。path参数应该是源代码来源的“路径”，它可以是一个抽象概念（例如，位置在一个zip文件中）。

    通过运行`exec（code， module .__ dict __）`，随后的代码对象可以在模块中执行它。

    版本3.4中的新功能。

    在版本3.5中更改：使方法变为静态。

  `exec_module`(module)

    `Loader.exec_module()`的实现。

    版本3.4中的新功能。

  `load_module`(fullname)

    `Loader.load_module()`的实现。

    从版本3.4开始弃用：改为使用`exec_module()`。

class `importlib.abc.``ExecutionLoader`

  一个从`InspectLoader`继承的抽象基类，它在实现时帮助模块作为脚本执行。ABC表示可选的 PEP 302协议。

  abstractmethod `get_filename`(fullname)

    一个抽象方法，用于返回指定模块的`__file__`的值。如果没有路径可用，则引发`ImportError`。

    如果源代码可用，那么该方法应该返回源文件的路径，而不管是否使用字节码来加载模块。

    在版本3.4中更改：引发`ImportError`而不是`NotImplementedError`。

class `importlib.abc.``FileLoader`(fullname, path)

  一个从`ResourceLoader`和`ExecutionLoader`继承的抽象基类，提供了`ResourceLoader.get_data()`和`ExecutionLoader.get_filename()`

  fullname参数是加载程序要处理的模块的完全解析名称。path参数是模块文件的路径。

  版本3.3中的新功能。

  `name`

    加载器可以处理的模块的名称。

  `path`

    模块文件的路径。

  `load_module`(fullname)

    调用super的`load_module()`。

    从版本3.4开始弃用：改为使用`Loader.exec_module()`。

  abstractmethod `get_filename`(fullname)

    返回`path`。

  abstractmethod `get_data`(path)

    将路径读取为二进制文件并从中返回字节。

class `importlib.abc.``SourceLoader`

  用于实现源文件（可选）和字节码文件加载的抽象基类。该类继承于`ResourceLoader`和`ExecutionLoader`，需要执行：

  - `ResourceLoader.get_data()`

  - `ExecutionLoader.get_filename()`

      只应该返回源文件的路径；不支持无源加载。

  这个类定义的抽象方法是添加可选的字节码文件支持。不执行这些可选方法（或导致它们引发`NotImplementedError`）会导致加载器只能使用源代码。实现这些方法允许加载器使用source 和字节码文件；它不允许仅提供字节码的无源加载。字节码文件是一种优化，可以通过删除Python编译器的解析步骤来加速加载，因此不会暴露字节码特定的API。

  `path_stats`(path)

    可选的抽象方法，它返回包含关于指定路径的元数据的`dict`。支持的字典键是：

    - `'mtime'`（强制）：表示源代码修改时间的整数或浮点数；
    - `'size'`（可选）：源代码的字节大小。

    字典中的任何其他键都将被忽略，以允许将来的扩展。如果路径无法处理，则引发`OSError`。

    版本3.3中的新功能。

    版本3.4中改变：引发`OSError`而不是`NotImplementedError`。

  `path_mtime`(path)

    可选抽象方法，返回指定路径的修改时间。

    从版本3.3开始不推荐使用：此方法已弃用，以支持`path_stats()`。您不必实现它，但它仍然可用于兼容性目的。如果路径无法处理，请引发`OSError`。

    版本3.4中改变：引发`OSError`而不是`NotImplementedError`。

  `set_data`(path, data)

    将指定字节写入文件路径的可选抽象方法。任何不存在的中间目录都将被自动创建。

    由于路径是只读的（`errno.EACCES` / `PermissionError`），因此写入路径失败时，请勿传播异常。

    在版本3.4中更改：调用时不再引发`NotImplementedError`。

  `get_code`(fullname)

    `InspectLoader.get_code()`的具体实现。

  `exec_module`(module)

    > Concrete implementation of `Loader.exec_module()`.

    版本3.4中的新功能。

  `load_module`(fullname)

    `Loader.load_module()`的具体实现。

    从版本3.4开始弃用：改为使用`exec_module()`。

  `get_source`(fullname)

    `InspectLoader.get_source()`的具体实现。

  `is_package`(fullname)

    `InspectLoader.is_package()`的具体实现。如果一个模块的文件路径（如`ExecutionLoader.get_filename()`）提供的文件路径是一个名为`__init__`的文件，则当文件扩展名被删除时，该模块将被确定为一个包和模块名称本身不会以`__init__`结尾。

## 31.5.4. `importlib.machinery` - 进口商和路径挂钩

源代码： Lib/importlib/machinery.py

该模块包含帮助`import`查找和加载模块的各种对象。

`importlib.machinery.``SOURCE_SUFFIXES`

  表示源模块的识别文件后缀的字符串列表。

  版本3.3中的新功能。

`importlib.machinery.``DEBUG_BYTECODE_SUFFIXES`

  表示非优化字节码模块的文件后缀的字符串列表。

  版本3.3中的新功能。

  从版本3.5开始弃用：改为使用`BYTECODE_SUFFIXES`。

`importlib.machinery.``OPTIMIZED_BYTECODE_SUFFIXES`

  代表优化字节码模块的文件后缀的字符串列表。

  版本3.3中的新功能。

  从版本3.5开始弃用：改为使用`BYTECODE_SUFFIXES`。

`importlib.machinery.``BYTECODE_SUFFIXES`

  代表字节码模块（包括前导点）的识别文件后缀的字符串列表。

  版本3.3中的新功能。

  在版本3.5中更改：该值不再依赖于`__debug__`。

`importlib.machinery.``EXTENSION_SUFFIXES`

  表示扩展模块的识别文件后缀的字符串列表。

  版本3.3中的新功能。

`importlib.machinery.``all_suffixes`()

  返回表示由标准导入机制识别的模块的所有文件后缀的字符串组合列表。这是代码的帮助器，它只需知道文件系统路径是否可能引用模块而不需要有关模块种类的任何细节（例如，`inspect.getmodulename()`）。

  版本3.3中的新功能。

class `importlib.machinery.``BuiltinImporter`

  内置模块的importer。所有已知的内置模块都列在`sys.builtin_module_names`中。该类实现`importlib.abc.MetaPathFinder`和`importlib.abc.InspectLoader` ABC。

  只有类方法是由这个类定义的，以减轻实例化的需要。

  版本3.5中改变：作为 PEP 489的一部分，内建导入器现在实现`Loader.create_module()` `Loader.exec_module()`

class `importlib.machinery.``FrozenImporter`

  冻结模块的importer。该类实现`importlib.abc.MetaPathFinder`和`importlib.abc.InspectLoader` ABC。

  只有类方法是由这个类定义的，以减轻实例化的需要。

class `importlib.machinery.``WindowsRegistryFinder`

  Finder for modules declared in the Windows registry. 这个类实现了`importlib.abc.Finder` ABC。

  只有类方法是由这个类定义的，以减轻实例化的需要。

  版本3.3中的新功能。

class `importlib.machinery.``PathFinder`

  A Finder用于`sys.path`和程序包`__path__`属性。这个类实现了`importlib.abc.MetaPathFinder` ABC。

  只有类方法是由这个类定义的，以减轻实例化的需要。

  classmethod `find_spec`(fullname, path=None, target=None)

    尝试为`sys.path`上由全名指定的模块或路径中定义的模块找到spec / T6>。对于搜索到的每个路径条目，检查`sys.path_importer_cache`。如果找到一个非错误的对象，那么它将用作path entry finder来查找正在搜索的模块。如果在`sys.path_importer_cache`中找不到任何条目，那么将搜索`sys.path_hooks`中的路径条目的查找器，并且如果找到，则存储在`sys.path_importer_cache`以及正在查询的模块。如果没有找到finder，则`None`都存储在缓存中并返回。

    版本3.4中的新功能。

    Changed in version 3.5: If the current working directory – represented by an empty string – is no longer valid then `None` is returned but no value is cached in `sys.path_importer_cache`.

  classmethod `find_module`(fullname, path=None)

    一个围绕`find_spec()`的传统封装。

    从版本3.4开始弃用：改为使用`find_spec()`。

  classmethod `invalidate_caches`()

    在存储在`sys.path_importer_cache`中的所有查找器中调用`importlib.abc.PathEntryFinder.invalidate_caches()`。

  在版本3.4中更改：使用当前工作目录`''`调用`sys.path_hooks`中的对象。空字符串）。

class `importlib.machinery.``FileFinder`(path, *loader_details)

  `importlib.abc.PathEntryFinder`的具体实现，它缓存文件系统的结果。

  path参数是查找器负责搜索的目录。

  loader_details参数是可变数量的2项元组，每个元组包含加载程序和加载程序识别的一系列文件后缀。预计装入程序是可接受的，它接受模块名称的两个参数和找到的文件的路径。

  取景器将根据需要缓存目录内容，为每个模块搜索进行统计调用以验证缓存未过期。因为缓存过期依赖于操作系统的文件系统状态信息的粒度，所以存在潜在的争用条件：搜索模块，创建新文件，然后搜索新文件所代表的模块。如果操作发生的速度足以满足stat调用的粒度，那么模块搜索将失败。为防止这种情况发生，当您动态创建模块时，请务必调用`importlib.invalidate_caches()`。

  版本3.3中的新功能。

  `path`

    查找器将搜索的路径。

  `find_spec`(fullname, target=None)

    尝试在`path`内找到处理fullname的规范。

    版本3.4中的新功能。

  `find_loader`(fullname)

    试图在`path`中找到加载器来处理fullname。

  `invalidate_caches`()

    清除内部缓存。

  classmethod `path_hook`(*loader_details)

    返回闭包以在`sys.path_hooks`上使用的类方法。一个`FileFinder`的实例由闭包使用直接给闭包的路径参数和loader_details间接返回。

    如果闭包的参数不是现有目录，则引发`ImportError`。

class `importlib.machinery.``SourceFileLoader`(fullname, path)

  通过继承`importlib.abc.FileLoader`来具体实现`importlib.abc.SourceLoader`，并提供其他方法的一些具体实现。

  版本3.3中的新功能。

  `name`

    该加载器将处理的模块的名称。

  `path`

    源文件的路径。

  `is_package`(fullname)

    如果`path`显示为包，则返回true。

  `path_stats`(path)

    `importlib.abc.SourceLoader.path_stats()`的具体实现。

  `set_data`(path, data)

    `importlib.abc.SourceLoader.set_data()`的具体实现。

  `load_module`(name=None)

    `importlib.abc.Loader.load_module()`的具体实现，其中指定要加载的模块的名称是可选的。

class `importlib.machinery.``SourcelessFileLoader`(fullname, path)

  `importlib.abc.FileLoader`的具体实现可以导入字节码文件（即没有源代码文件存在）。

  请注意，直接使用字节码文件（从而不是源代码文件）会禁止所有Python实现或更改字节码格式的Python新版本使用您的模块。

  版本3.3中的新功能。

  `name`

    加载器将处理的模块的名称。

  `path`

    字节码文件的路径。

  `is_package`(fullname)

    根据`path`确定模块是否为包。

  `get_code`(fullname)

    返回从`path`创建的`name`的代码对象。

  `get_source`(fullname)

    返回`None`，因为使用此加载程序时，字节码文件没有源代码。

  `load_module`(name=None)

  `importlib.abc.Loader.load_module()`的具体实现，其中指定要加载的模块的名称是可选的。

class `importlib.machinery.``ExtensionFileLoader`(fullname, path)

  扩展模块的`importlib.abc.ExecutionLoader`的具体实现。

  fullname参数指定加载程序要支持的模块的名称。path参数是扩展模块文件的路径。

  版本3.3中的新功能。

  `name`

    加载程序支持的模块的名称。

  `path`

    扩展模块的路径。

  `create_module`(spec)

    按照 PEP 489从给定规范创建模块对象。

    版本3.5中的新功能。

  `exec_module`(module)

    根据 PEP 489初始化给定的模块对象。

    版本3.5中的新功能。

  `is_package`(fullname)

    如果文件路径基于`EXTENSION_SUFFIXES`指向程序包的`__init__`模块，则返回`True`。

  `get_code`(fullname)

    返回`None`，因为扩展模块缺少代码对象。

  `get_source`(fullname)

    返回`None`，因为扩展模块没有源代码。

  `get_filename`(fullname)

    返回`path`。

    版本3.4中的新功能。

class `importlib.machinery.``ModuleSpec`(name, loader, *, origin=None, loader_state=None, is_package=None)

  模块的导入系统相关状态的规范。

  版本3.4中的新功能。

  `name`

  (`__name__`)

  一个字符串，用于模块的完全限定名称。

  `loader`

  (`__loader__`)

  用于加载的加载器。对于命名空间包，应将其设置为None。

  `origin`

  (`__file__`)

  装载模块的地点的名称，例如内置模块的“builtin”和从源加载的模块的文件名。通常应该设置“origin”，但可能是None（默认值），表示它是未指定的。

  `submodule_search_locations`

  (`__path__`)

  如果是包（否则无），可以在哪里找到子模块的字符串列表。

  `loader_state`

  装载期间使用的额外模块特定数据的容器（或无）。

  `cached`

  (`__cached__`)

  字符串，用于编译模块应存储的位置（或无）。

  `parent`

  (`__package__`)

  （只读）模块作为子模块所属的软件包的完全限定名称（或无）。

  `has_location`

  指示模块的“origin”属性是否指向可加载位置的布尔值。

## 31.5.5. `importlib.util` — importer的实用程序代码

源代码： Lib/importlib/util.py

该模块包含帮助构建importer的各种对象。

`importlib.util.``MAGIC_NUMBER`

  代表字节码版本号的字节。如果您需要加载/写入字节码的帮助，请考虑`importlib.abc.SourceLoader`。

  版本3.4中的新功能。

`importlib.util.``cache_from_source`(path, debug_override=None, *, optimization=None)

  Return the PEP 3147/PEP 488 path to the byte-compiled file associated with the source path. 例如，如果path是`/foo/bar/baz.py`，则返回值为`/foo/bar/__pycache__/baz.cpython-32.pyc` for Python 3.2。`cpython-32`字符串来自当前的魔术标签（参见`get_tag()`；如果没有定义`sys.implementation.cache_tag`，则`NotImplementedError`会被提出）。

  optimization参数用于指定字节码文件的优化级别。一个空字符串表示没有优化，所以`/foo/bar/baz.py`与优化 `''`将导致字节码路径为`/foo/bar/__pycache__/baz.cpython-32.pyc` `None`会导致使用interpter的优化级别。使用任何其他值的字符串表示形式，所以`/foo/bar/baz.py`与优化 `2`将导致字节码路径为`/foo/bar/__pycache__/baz.cpython-32.opt-2.pyc` The string representation of optimization can only be alphanumeric, else `ValueError` is raised.

  debug_override参数已弃用，可用于覆盖`__debug__`的系统值。一个`True`值相当于将优化设置为空字符串。A `False`的值与优化至`1`的设置相同。如果debug_override和优化都不是`None`，则引发`TypeError`。

  版本3.4中的新功能。

  在版本3.5中更改：添加了优化参数，并且不推荐使用debug_override参数。

`importlib.util.``source_from_cache`(path)

  将路径指定给 PEP 3147文件名，返回关联的源代码文件路径。例如，如果路径为`/foo/bar/__pycache__/baz.cpython-32.pyc`，则返回的路径为`/foo/bar/baz.py`。path need not exist, however if it does not conform to PEP 3147 or PEP 488 format, a `ValueError` is raised. 如果未定义`sys.implementation.cache_tag`，则会引发`NotImplementedError`。

  版本3.4中的新功能。

`importlib.util.``decode_source`(source_bytes)

  解码表示源代码的给定字节，并将其作为带有通用换行符的字符串返回（如`importlib.abc.InspectLoader.get_source()`所要求的）。

  版本3.4中的新功能。

`importlib.util.``resolve_name`(name, package)

  将相对模块名称解析为绝对模块名称。

  如果name没有前导点，则简单地返回name。这允许使用诸如`importlib.util.resolve_name（'sys'， __ package __）`，而不检查package参数是必需的。

  `ValueError` is raised if name is a relative module name but package is a false value (e.g. `None`或空字符串）。`ValueError` is also raised a relative name would escape its containing package (e.g. 请求`spam`包中的`..bacon`）。

  版本3.3中的新功能。

`importlib.util.``find_spec`(name, package=None)

  查找模块的spec，可选地相对于指定的包名称。If the module is in `sys.modules`, then `sys.modules[name].__spec__` is returned (unless the spec would be `None` or is not set, in which case `ValueError` is raised). 否则，使用`sys.meta_path`完成搜索。`None` is returned if no spec is found.

  如果name用于子模块（包含点），则会自动导入父模块。

  name和package与`import_module()`的工作方式相同。

  版本3.4中的新功能。

`importlib.util.``module_from_spec`(spec)

  根据spec和`spec.loader.create_module()`创建一个新模块。

  如果`spec.loader.create_module()`没有返回`None`，那么任何预先存在的属性都不会被重置。另外，如果在访问spec时触发，或者在模块上设置属性，则不会引发`AttributeError`。

  此功能优于使用`types.ModuleType`创建新模块，因为spec用于在模块上设置尽可能多的导入控制属性。

  版本3.5中的新功能。

`@``importlib.util.``module_for_loader`

  用于`importlib.abc.Loader.load_module()`的decorator来处理选择要加载的适当模块对象。期望装饰方法具有带有两个位置参数（例如，`load_module(self, module)`) for which the second argument will be the module object to be used by the loader. 请注意，由于假设有两个参数，装饰器不能用于静态方法。

  装饰好的方法将按照loader的预期加载模块的名称。如果在`sys.modules`中找不到该模块，则会构建一个新模块。无论模块来自何处，设置为self和`__package__`的`__loader__`都根据`importlib.abc.InspectLoader.is_package()`返回（如果可用）。这些属性被无条件设置为支持重新加载。

  如果装饰方法引发异常，并且将模块添加到`sys.modules`中，则模块将被删除，以防止部分初始化的模块留在`sys.modules` 如果该模块已经在`sys.modules`中，那么它就被单独保留。

  Changed in version 3.3: `__loader__` and `__package__` are automatically set (when possible).

  版本3.4中改变：设置`__name__`，`__loader__` `__package__`无条件支持重新加载。

  从版本3.4开始弃用：现在，导入机器直接执行此功能提供的所有功能。

`@``importlib.util.``set_loader`

  用于`importlib.abc.Loader.load_module()`的decorator在返回的模块上设置`__loader__`属性。如果该属性已经设置，装饰器不做任何事情。假定包装方法的第一个位置参数（即，`self`）是`__loader__`应该设置的值。

  Changed in version 3.4: Set `__loader__` if set to `None`, as if the attribute does not exist.

  从版本3.4开始弃用：进口机械自动处理。

`@``importlib.util.``set_package`

  用于`importlib.abc.Loader.load_module()`的decorator在返回的模块上设置`__package__`属性。如果`__package__`被设置并且其值不是`None`，它将不会被更改。

  从版本3.4开始弃用：进口机械自动处理。

`importlib.util.``spec_from_loader`(name, loader, *, origin=None, is_package=None)

  基于加载程序创建`ModuleSpec`实例的工厂函数。这些参数与ModuleSpec具有相同的含义。该函数使用可用的loader API（例如`InspectLoader.is_package()`）来填写规范中缺少的任何信息。

  版本3.4中的新功能。

`importlib.util.``spec_from_file_location`(name, location, *, loader=None, submodule_search_locations=None)

  基于文件路径创建`ModuleSpec`实例的工厂函数。缺少的信息将通过使用加载器API以及模块将基于文件的含义填充到规范中。

  版本3.4中的新功能。

class `importlib.util.``LazyLoader`(loader)

  推迟模块加载程序执行的类，直到模块具有访问的属性为止。

  该类仅与定义`exec_module()`的加载程序一起使用，以控制需要使用哪个模块类型的模块。出于同样的原因，加载程序的`create_module()`方法将被忽略（即加载程序的方法应该只返回`None`；这不包括`BuiltinImporter`和`ExtensionFileLoader` Finally, modules which substitute the object placed into `sys.modules` will not work as there is no way to properly replace the module references throughout the interpreter safely; `ValueError` is raised if such a substitution is detected.

  注意

  对于启动时间很关键的项目，如果从未使用模块，该类可以潜在地降低加载模块的成本。For projects where startup time is not essential then use of this class is heavily discouraged due to error messages created during loading being postponed and thus occurring out of context.

  版本3.5中的新功能。

  classmethod `factory`(loader)

    一个静态方法，它返回一个可创建懒惰加载器的可调用对象。这是为了在加载器按类而不是按实例传递的情况下使用。

        suffixes = importlib.machinery.SOURCE_SUFFIXES
        loader = importlib.machinery.SourceFileLoader
        lazy_loader = importlib.util.LazyLoader.factory(loader)
        finder = importlib.machinery.FileFinder(path, (lazy_loader, suffixes))