importlib --- The implementation of import

3.1 新版功能.

源代码: Lib/importlib/__init__.py


介绍

目的 importlib 包裹是两折的。一是提供 import 声明(因此,通过扩展, __import__() 函数)在python源代码中。这提供了 import 它可以移植到任何Python解释器。这也提供了一个比用编程语言而不是Python实现更容易理解的实现。

第二,要实现的组件 import 在此包中公开,使用户更容易创建自己的自定义对象(通常称为 importer )参与输入过程。

参见

这个 import 陈述

的语言引用 import 语句。

Packages specification

封装的原始规格。自编写本文档以来,一些语义发生了变化(例如,基于 None 在里面 sys.modules

这个 __import__() 功能

这个 import 语句是这个函数的句法糖。

PEP 235

在不区分大小写的平台上导入

PEP 263

定义python源代码编码

PEP 302

新导入挂钩

PEP 328

导入:多行和绝对/相对

PEP 366

主模块显式相对导入

PEP 420

隐式命名空间包

PEP 451

导入系统的modulespec类型

PEP 488

消除PYO文件

PEP 489

多相扩展模块初始化

PEP 552

确定性Pycs

PEP 3120

使用UTF-8作为默认源编码

PEP 3147

PYC存储库目录

功能

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

内置的实现 __import__() 功能。

注解

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

importlib.import_module(name, package=None)

导入模块。这个 name 参数指定以绝对或相对术语(例如 pkg.mod..mod )。如果名称是用相对术语指定的,则 包裹 参数必须设置为要用作解析包名称的定位点的包的名称(例如 import_module('..mod', 'pkg.subpkg') 将输入 pkg.mod

这个 import_module() 函数充当一个简化的封装器 importlib.__import__() . 这意味着函数的所有语义都是从 importlib.__import__() . 这两个函数之间最重要的区别是 import_module() 返回指定的包或模块(例如 pkg.mod__import__() 返回顶级包或模块(例如 pkg

如果动态导入自解释器开始执行以来创建的模块(例如,创建了一个python源文件),则可能需要调用 invalidate_caches() 以便导入系统注意到新模块。

在 3.3 版更改: 父包将自动导入。

importlib.find_loader(name, path=None)

在指定的 path . 如果模块在 sys.modules 然后 sys.modules[name].__loader__ 返回(除非加载程序 None 或未设置,在这种情况下 ValueError 提高了)。否则,使用 sys.meta_path 完成了。 None 如果找不到加载程序,则返回。

点式名称没有隐式导入其父项,因为这需要加载它们,可能不需要。要正确导入子模块,需要导入子模块的所有父包,并使用正确的参数 path .

3.3 新版功能.

在 3.4 版更改: 如果 __loader__ 未设置,升高 ValueError ,就像属性设置为 None .

3.4 版后已移除: 使用 importlib.util.find_spec() 相反。

importlib.invalidate_caches()

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

3.3 新版功能.

importlib.reload(module)

重新加载以前导入的 模块 . 参数必须是一个模块对象,因此它以前必须成功导入。如果您已经使用外部编辑器编辑了模块源文件,并且希望在不离开Python解释器的情况下试用新版本,那么这将非常有用。返回值是模块对象(如果重新导入导致将不同的对象放入 sys.modules

什么时候? reload() 执行:

  • python模块的代码被重新编译并重新执行模块级代码,通过重用 loader 最初加载模块。这个 init 扩展模块的函数没有第二次调用。

  • 与Python中的所有其他对象一样,旧对象只有在其引用计数降至零后才会被回收。

  • 模块命名空间中的名称将更新为指向任何新对象或更改的对象。

  • 对旧对象的其他引用(如模块外部的名称)不会反弹以引用新对象,如果需要,则必须在出现新对象的每个命名空间中进行更新。

还有许多其他注意事项:

当模块重新加载时,它的字典(包含模块的全局变量)将被保留。重新定义名称将覆盖旧的定义,因此这通常不是问题。如果模块的新版本未定义由旧版本定义的名称,则保留旧定义。如果模块维护对象的全局表或缓存,则可以利用此功能 try 语句,它可以测试表是否存在,如果需要,则跳过其初始化::

try:
    cache
except NameError:
    cache = {}

通常,重新加载内置或动态加载的模块并不十分有用。重装 sys__main__builtins 不建议使用其他关键模块。在许多情况下,扩展模块不能被设计为多次初始化,并且在重新加载时可能以任意方式失败。

如果某个模块使用 fromimport ……调用 reload() 因为另一个模块没有重新定义从它导入的对象——一种方法是重新执行 from 声明,另一个是使用 import 和限定名( module.name 相反。

如果一个模块实例化一个类的实例,那么重新加载定义该类的模块不会影响实例的方法定义——它们继续使用旧的类定义。派生类也是如此。

3.4 新版功能.

在 3.7 版更改: ModuleNotFoundError 当重新加载的模块缺少 ModuleSpec .

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

源代码: Lib/importlib/abc.py


这个 importlib.abc 模块包含 import .还提供了核心抽象基类的一些子类来帮助实现核心ABC。

ABC层次结构:

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

表示 finder .

3.3 版后已移除: 使用 MetaPathFinderPathEntryFinder 相反。

abstractmethod find_module(fullname, path=None)

用于查找 loader 对于指定的模块。最初在中指定 PEP 302 ,此方法用于 sys.meta_path 在基于路径的导入子系统中。

在 3.4 版更改: 返回 None 当调用而不是引发时 NotImplementedError .

class importlib.abc.MetaPathFinder

表示 meta path finder . 为了兼容性,这是 Finder .

3.3 新版功能.

find_spec(fullname, path, target=None)

用于查找 spec 对于指定的模块。如果这是顶级导入, pathNone . 否则,这是对子包或模块的搜索,并且 path 将是的价值 __path__ 来自父包。如果找不到规格, None 返回。当通过时, target 是一个模块对象,finder可以使用它对返回的规范进行更合理的猜测。 importlib.util.spec_from_loader() 可能有助于具体实施 MetaPathFinders .

3.4 新版功能.

find_module(fullname, path)

用于查找 loader 对于指定的模块。如果这是顶级导入, pathNone . 否则,这是对子包或模块的搜索,并且 path 将是的价值 __path__ 来自父包。如果找不到加载器, None 返回。

如果 find_spec() 定义后,提供向后兼容的功能。

在 3.4 版更改: 返回 None 当调用而不是引发时 NotImplementedError .可以使用 find_spec() 提供功能。

3.4 版后已移除: 使用 find_spec() 相反。

invalidate_caches()

一种可选方法,调用时应使查找程序使用的任何内部缓存失效。被使用 importlib.invalidate_caches() 当对上的所有查找器的缓存无效时 sys.meta_path .

在 3.4 版更改: 返回 None 当调用而不是 NotImplemented .

class importlib.abc.PathEntryFinder

表示 path entry finder . 尽管它与 MetaPathFinderPathEntryFinder 仅用于由提供的基于路径的导入子系统 PathFinder . 这个ABC是 Finder 仅出于兼容性原因。

3.3 新版功能.

find_spec(fullname, target=None)

用于查找 spec 对于指定的模块。查找器将仅在 path entry 分配给它的。如果找不到规格, None 返回。当通过时, target 是一个模块对象,finder可以使用它对返回的规范进行更合理的猜测。 importlib.util.spec_from_loader() 可能有助于具体实施 PathEntryFinders .

3.4 新版功能.

find_loader(fullname)

用于查找 loader 对于指定的模块。返回的2元组 (loader, portion) 在哪里? portion 是一系列文件系统位置,这些位置构成了命名空间包的一部分。加载器可能 None 当指定 portion 表示文件系统位置对命名空间包的贡献。空列表可用于 portion 表示加载程序不是命名空间包的一部分。如果 loaderNoneportion 是空列表,则找不到命名空间包的加载程序或位置(即找不到模块的任何内容)。

如果 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 对于加载器的确切定义。

希望支持资源读取的加载程序应实现 get_resource_reader(fullname) 规定的方法 importlib.abc.ResourceReader .

在 3.7 版更改: 介绍了选修课 get_resource_reader() 方法。

create_module(spec)

一种方法,在导入模块时返回要使用的模块对象。此方法可能返回 None ,表示应该执行默认的模块创建语义。

3.4 新版功能.

在 3.5 版更改: 从python 3.6开始,当 exec_module() 定义。

exec_module(module)

在导入或重新加载模块时,在自己的命名空间中执行模块的抽象方法。当 exec_module() 被调用。当这种方法存在时, create_module() 必须定义。

3.4 新版功能.

在 3.6 版更改: create_module() 还必须定义。

load_module(fullname)

用于加载模块的遗留方法。如果无法加载模块, ImportError 引发,否则返回加载的模块。

如果请求的模块已存在于 sys.modules ,应该使用该模块并重新加载。否则,加载程序应创建一个新模块并将其插入 sys.modules 在任何加载开始之前,防止从导入中递归。如果加载器插入模块而装载失败,加载器必须从 sys.modules ;模块已在 sys.modules 在加载程序开始执行之前,应单独执行(请参见 importlib.util.module_for_loader()

加载程序应该在模块上设置几个属性。(请注意,当重新加载模块时,其中一些属性可能会发生更改):

什么时候? exec_module() 是可用的,然后提供向后兼容的功能。

在 3.4 版更改: 提高 ImportError 当调用而不是 NotImplementedError . 提供的功能 exec_module() 可用。

3.4 版后已移除: 用于加载模块的推荐API是 exec_module() (和 create_module() )加载程序应该实现它,而不是加载模块()。在执行exec_module()时,导入机制负责加载_module()的所有其他职责。

module_repr(module)

一种遗留方法,在实现时,它以字符串的形式计算并返回给定模块的repr。模块类型的默认repr()将根据需要使用此方法的结果。

3.3 新版功能.

在 3.4 版更改: 使成为可选的而不是抽象方法。

3.4 版后已移除: 输入机器现在自动处理这个问题。

class importlib.abc.ResourceReader

被TraversableReader取代

abstract base class 提供阅读能力 资源 .

从ABC的角度来看, 资源 是在包中传送的二进制项目。通常,这类似于一个数据文件,它位于 __init__.py 包的文件。这个类的目的是帮助抽象出对这些数据文件的访问,这样无论包及其数据文件是否存储在例如zip文件中,还是存储在文件系统中。

对于此类的任何方法,都是 资源 参数应为 path-like object 它在概念上只表示一个文件名。这意味着在 资源 参数。这是因为读卡器所在的包的位置充当“目录”。因此,目录和文件名的隐喻分别是包和资源。这也是这个类的实例应该直接关联到特定包(而不是潜在地表示多个包或一个模块)的原因。

希望支持资源读取的加载程序应提供一个名为 get_resource_reader(fullname) 它返回一个实现ABC接口的对象。如果由fullname指定的模块不是包,则此方法应返回 None . 只有当指定的模块是包时,才应返回与此ABC兼容的对象。

3.7 新版功能.

abstractmethod open_resource(resource)

返回打开的, file-like object 用于二进制读取 资源 .

如果找不到资源, FileNotFoundError 提高了。

abstractmethod resource_path(resource)

将文件系统路径返回到 资源 .

如果文件系统上不具体存在该资源,则引发 FileNotFoundError .

abstractmethod is_resource(name)

返回 True 如果命名 name 被视为资源。 FileNotFoundError 如果 name 不存在。

abstractmethod contents()

返回一个 iterable 包内容上的字符串。请注意,不要求迭代器返回的所有名称都是实际资源,例如,可以接受为其返回名称 is_resource() 是假的。

允许返回非资源名称是为了允许预先知道如何存储包及其资源,并且非资源名称将很有用的情况。例如,允许返回子目录名,这样当知道包和资源存储在文件系统上时,就可以直接使用这些子目录名。

抽象方法返回无项的iterable。

class importlib.abc.ResourceLoader

的抽象基类 loader 它实现了可选的 PEP 302 从存储后端加载任意资源的协议。

3.7 版后已移除: 该ABC被否决,赞成支持通过 importlib.abc.ResourceReader .

abstractmethod get_data(path)

返回位于的数据字节的抽象方法 path . 具有类似于存储后端的文件(允许存储任意数据)的加载器可以实现此抽象方法以直接访问存储的数据。 OSError 如果 path 找不到。这个 path 应使用模块的 __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)

如果模块是包,则返回真值的抽象方法,否则返回假值。 ImportError 如果 loader 找不到模块。

在 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)

继承自的抽象基类 ResourceLoaderExecutionLoader ,提供 ResourceLoader.get_data()ExecutionLoader.get_filename() .

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

3.3 新版功能.

name

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

path

模块文件的路径。

load_module(fullname)

调用超级 load_module() .

3.4 版后已移除: 使用 Loader.exec_module() 相反。

abstractmethod get_filename(fullname)

返回 path .

abstractmethod get_data(path)

读数 path 作为一个二进制文件并返回其中的字节。

class importlib.abc.SourceLoader

用于实现源(和可选的字节码)文件加载的抽象基类。类从两者继承 ResourceLoaderExecutionLoader ,要求执行:

此类定义的抽象方法用于添加可选的字节码文件支持。没有实现这些可选方法(或导致它们 NotImplementedError )使加载程序只使用源代码。实现这些方法允许加载程序使用源 and 字节码文件;它不允许 无细胞的 仅提供字节码的加载。字节码文件是一种通过删除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)

具体实施 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__ 删除文件扩展名时 and 模块名称本身不以 __init__ .

class importlib.abc.Traversable

具有路径库路径适合遍历目录和打开文件的方法。

3.9 新版功能.

class importlib.abc.TraversableReader

资源读取器的抽象基类,能够为 files 接口。子类ResourceReader并提供ResourceReader抽象方法的具体实现。因此,任何提供TraversableReader的加载器也提供ResourceReader。

希望支持资源读取的加载程序应实现此接口。

3.9 新版功能.

importlib.resources --资源

源代码: Lib/importlib/resources.py


3.7 新版功能.

该模块利用python的导入系统提供对 资源 在内部 封装 . 如果可以导入包,则可以访问该包中的资源。可以以二进制或文本模式打开或读取资源。

资源大致类似于目录中的文件,不过要记住这只是一个比喻,这一点很重要。资源和包 必须作为物理文件和目录存在于文件系统中。

注解

此模块提供的功能与 pkg_resources Basic Resource Access 没有该包的性能开销。这使得包中包含的读取资源更容易,语义更稳定和一致。

此模块的独立后端口提供了有关 using importlib.resourcesmigrating from pkg_resources to importlib.resources .

希望支持资源读取的加载程序应实现 get_resource_reader(fullname) 规定的方法 importlib.abc.ResourceReader .

定义了以下类型。

importlib.resources.Package

这个 Package 类型定义为 Union[str, ModuleType] . 这意味着函数描述接受 Package ,可以传入字符串或模块。模块对象必须具有可解析的 __spec__.submodule_search_locations 那不是 None .

importlib.resources.Resource

此类型描述传递到此包中的各种函数的资源名称。定义如下: Union[str, os.PathLike] .

以下功能可用。

importlib.resources.files(package)

返回一个 importlib.resources.abc.Traversable 对象,表示包(think目录)及其资源(think文件)的资源容器。可遍历的可以包含其他容器(考虑子目录)。

包裹 是符合 Package 要求。

3.9 新版功能.

importlib.resources.open_binary(package, resource)

打开以进行二进制读取 资源 在内部 包裹 .

包裹 是符合 Package 要求。 资源 是要在其中打开的资源的名称 包裹 ;它可能不包含路径分隔符,也可能没有子资源(即它不能是目录)。此函数返回 typing.BinaryIO 例如,一个二进制I/O流打开进行读取。

importlib.resources.open_text(package, resource, encoding='utf-8', errors='strict')

打开以阅读文本 资源 在内部 包裹 . 默认情况下,资源以utf-8的形式打开进行读取。

包裹 是符合 Package 要求。 资源 是要在其中打开的资源的名称 包裹 ;它可能不包含路径分隔符,也可能没有子资源(即它不能是目录)。 encodingerrors 与内置的含义相同 open() .

此函数返回 typing.TextIO 例如,一个打开供读取的文本I/O流。

importlib.resources.read_binary(package, resource)

读取并返回 资源 在内部 包裹 作为 bytes .

包裹 是符合 Package 要求。 资源 是要在其中打开的资源的名称 包裹 ;它可能不包含路径分隔符,也可能没有子资源(即它不能是目录)。此函数将资源的内容返回为 bytes .

importlib.resources.read_text(package, resource, encoding='utf-8', errors='strict')

阅读并返回 资源 在内部 包裹 作为一个 str . 默认情况下,内容读取为严格的UTF-8。

包裹 是符合 Package 要求。 资源 是要在其中打开的资源的名称 包裹 ;它可能不包含路径分隔符,也可能没有子资源(即它不能是目录)。 encodingerrors 与内置的含义相同 open() . 此函数将资源的内容返回为 str .

importlib.resources.path(package, resource)

将路径返回到 资源 作为实际文件系统路径。此函数返回用于 with 语句。上下文管理器提供 pathlib.Path 对象。

退出上下文管理器将清除需要从zip文件等资源提取时创建的任何临时文件。

包裹 是符合 Package 要求。 资源 是要在其中打开的资源的名称 包裹 ;它可能不包含路径分隔符,也可能没有子资源(即它不能是目录)。

importlib.resources.is_resource(package, name)

返回 True 如果存在名为的资源 name 在封装中,否则 False . 记住目录是 not 资源! 包裹 是符合 Package 要求。

importlib.resources.contents(package)

在包中的命名项上返回ITerable。无止境回报 str 资源(如文件)和非资源(如目录)。iterable不会递归到子目录中。

包裹 是符合 Package 要求。

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.MetaPathFinderimportlib.abc.InspectLoader ABC。

这个类只定义了类方法,以减轻实例化的需要。

在 3.5 版更改: 作为一部分 PEP 489 ,内置导入程序现在实现 Loader.create_module()Loader.exec_module()

class importlib.machinery.FrozenImporter

importer 对于冻结的模块。此类实现 importlib.abc.MetaPathFinderimportlib.abc.InspectLoader ABC。

这个类只定义了类方法,以减轻实例化的需要。

在 3.4 版更改: 获得 create_module()exec_module() 方法。

class importlib.machinery.WindowsRegistryFinder

Finder 用于在Windows注册表中声明的模块。此类实现 importlib.abc.MetaPathFinder 美国广播公司

这个类只定义了类方法,以减轻实例化的需要。

3.3 新版功能.

3.6 版后已移除: 使用 site 而是配置。默认情况下,未来版本的python可能不会启用此finder。

class importlib.machinery.PathFinder

A Finder 对于 sys.path 包装 __path__ 属性。此类实现 importlib.abc.MetaPathFinder 美国广播公司

这个类只定义了类方法,以减轻实例化的需要。

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

尝试查找 spec 对于由指定的模块 全名sys.path 或者,如果定义了,打开 path . 对于搜索的每个路径条目, sys.path_importer_cache 检查。如果找到非假对象,则将其用作 path entry finder 查找正在搜索的模块。如果在 sys.path_importer_cache 然后 sys.path_hooks 搜索路径条目的查找器,如果找到,则存储在 sys.path_importer_cache 以及有关模块的查询。如果找不到任何人,那么 None 都存储在缓存中并返回。

3.4 新版功能.

在 3.5 版更改: 如果当前工作目录(由空字符串表示)不再有效,则 None 返回但未缓存任何值 sys.path_importer_cache .

classmethod find_module(fullname, path=None)

传统封装 find_spec() .

3.4 版后已移除: 使用 find_spec() 相反。

classmethod invalidate_caches()

调用 importlib.abc.PathEntryFinder.invalidate_caches() 在存储的所有查找器上 sys.path_importer_cache 定义了方法。否则输入 sys.path_importer_cache 设置为 None 被删除。

在 3.7 版更改: 条目 None 在里面 sys.path_importer_cache 被删除。

在 3.4 版更改: 在中调用对象 sys.path_hooks 的当前工作目录 '' (即空字符串)。

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

具体实施 importlib.abc.PathEntryFinder 哪个缓存来自文件系统的结果。

这个 path 参数是finder负责搜索的目录。

这个 loader_details 参数是一个2项元组的变量,每个元组包含一个加载器和一个加载器识别的文件后缀序列。加载程序应该是可调用的,它接受模块名称和找到的文件路径的两个参数。

finder将根据需要缓存目录内容,对每个模块搜索进行stat调用,以验证缓存是否过期。由于缓存过时依赖于操作系统文件系统状态信息的粒度,因此存在一个潜在的竞争条件,即搜索模块、创建新文件,然后搜索新文件表示的模块。如果操作发生得足够快,能够适应stat调用的粒度,那么模块搜索将失败。为了防止这种情况发生,在动态创建模块时,请确保调用 importlib.invalidate_caches() .

3.3 新版功能.

path

查找器将搜索的路径。

find_spec(fullname, target=None)

尝试查找要处理的规范 全名 在内部 path .

3.4 新版功能.

find_loader(fullname)

尝试查找要处理的加载程序 全名 在内部 path .

invalidate_caches()

清除内部缓存。

classmethod path_hook(*loader_details)

一个类方法,返回用于 sys.path_hooks . 一个实例 FileFinder 由闭包使用直接给闭包的path参数返回,并且 loader_details 间接地。

如果闭包的参数不是现有目录, ImportError 提高了。

class importlib.machinery.SourceFileLoader(fullname, path)

具体实施 importlib.abc.SourceLoader 子类化 importlib.abc.FileLoader 并提供其他方法的一些具体实现。

3.3 新版功能.

name

此加载程序将处理的模块的名称。

path

源文件的路径。

is_package(fullname)

返回 True 如果 path 似乎是针对一个包。

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() 其中指定要加载的模块的名称是可选的。

3.6 版后已移除: 使用 importlib.abc.Loader.exec_module() 相反。

class importlib.machinery.SourcelessFileLoader(fullname, path)

具体实施 importlib.abc.FileLoader 可以导入字节码文件(即不存在源代码文件)。

请注意,直接使用字节码文件(因而不是源代码文件)会阻止所有Python实现或更改字节码格式的新版本使用模块。

3.3 新版功能.

name

加载程序将处理的模块的名称。

path

字节码文件的路径。

is_package(fullname)

确定模块是否是基于 path .

get_code(fullname)

返回的代码对象 name 创建自 path .

get_source(fullname)

返回 None 因为当使用这个加载程序时,字节码文件没有源。

load_module(name=None)

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

3.6 版后已移除: 使用 importlib.abc.Loader.exec_module() 相反。

class importlib.machinery.ExtensionFileLoader(fullname, path)

具体实施 importlib.abc.ExecutionLoader 对于扩展模块。

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

3.3 新版功能.

name

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

path

扩展模块的路径。

create_module(spec)

根据 PEP 489 .

3.5 新版功能.

exec_module(module)

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

3.5 新版功能.

is_package(fullname)

返回 True 如果文件路径指向包的 __init__ 基于模块 EXTENSION_SUFFIXES .

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)

模块的导入系统相关状态的规范。这通常作为模块的 __spec__ 属性。在下面的描述中,括号中的名称给出了直接在模块对象上可用的相应属性。例如。 module.__spec__.origin == module.__file__ . 但是请注意,当 价值观 通常是等效的,因为这两个对象之间没有同步,所以它们可以不同。因此,可以更新模块的 __path__ 在运行时,这不会自动反映在 __spec__.submodule_search_locations .

3.4 新版功能.

name

(__name__)

模块的完全限定名的字符串。

loader

(__loader__)

这个 Loader 加载模块时应使用的。 Finders 应该始终设置此设置。

origin

(__file__)

加载模块的位置的名称,例如内置模块的“built in”和从源加载模块的文件名。通常应设置“原点”,但可以 None (默认值),表示未指定(例如,对于命名空间包)。

submodule_search_locations

(__path__)

用于查找子模块的字符串列表(如果是包) (None 否则)。

loader_state

装载期间使用的额外模块特定数据容器(或 None

cached

(__cached__)

用于存储已编译模块的字符串(或 None

parent

(__package__)

(只读)应将模块作为子模块加载到的包的完全限定名称(或顶级模块的空字符串)。对于包裹,它与 __name__

has_location

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

importlib.util --importers实用代码

源代码: 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)

返回 PEP 3147/PEP 488 与源关联的字节编译文件的路径 path . 例如,如果 path/foo/bar/baz.py 返回值为 /foo/bar/__pycache__/baz.cpython-32.pyc 对于python 3.2。这个 cpython-32 字符串来自当前的magic标记(请参见 get_tag() 如果 sys.implementation.cache_tag 则未定义 NotImplementedError 将被引发)。

这个 优化 参数用于指定字节码文件的优化级别。空字符串表示没有优化,因此 /foo/bar/baz.py 用一个 优化 属于 '' 将导致字节码路径 /foo/bar/__pycache__/baz.cpython-32.pyc . None 导致使用解释器的优化级别。使用任何其他值的字符串表示,因此 /foo/bar/baz.py 用一个 优化 属于 2 将导致的字节码路径 /foo/bar/__pycache__/baz.cpython-32.opt-2.pyc . 的字符串表示形式 优化 只能是字母数字,否则 ValueError 提高了。

这个 debug_override 参数已弃用,可用于重写系统的值 __debug__ . 一 True 值等于设置值 optimization 到空字符串。一 False 值与设置相同 optimization1 . 如果两者 debug_override 一个 optimization 不是 None 然后 TypeError 提高了。

3.4 新版功能.

在 3.5 版更改: 这个 optimization 添加了参数,并且 debug_override 参数已弃用。

在 3.6 版更改: 接受一 path-like object .

importlib.util.source_from_cache(path)

鉴于 path 到A PEP 3147 文件名,返回关联的源代码文件路径。例如,如果 path/foo/bar/__pycache__/baz.cpython-32.pyc 返回的路径将是 /foo/bar/baz.py . path 但是,如果它不符合 PEP 3147PEP 488 格式,A ValueError 提高了。如果 sys.implementation.cache_tag 未定义, NotImplementedError 提高了。

3.4 新版功能.

在 3.6 版更改: 接受一 path-like object .

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', __spec__.parent) 而不进行检查以查看是否 套餐 需要论证。

ImportError 如果 name 是相对模块名,但 包裹 是一个错误值(例如。 None 或空字符串)。 ImportError 也会引发一个相对名称,该相对名称将转义其包含的包(例如,请求 ..bacon 从内部 spam 包装)。

3.3 新版功能.

在 3.9 版更改: 要提高与import语句的一致性,请 ImportError 而不是 ValueError 对于无效的相对导入尝试。

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

找到 spec 对于模块,可以选择相对于指定的 包裹 姓名。如果模块在 sys.modules 然后 sys.modules[name].__spec__ 返回(除非规范 None 或未设置,在这种情况下 ValueError 提高了)。否则,使用 sys.meta_path 完成了。 None 如果找不到规范,则返回。

如果 name 对于子模块(包含点),将自动导入父模块。

name包裹 工作原理与 import_module() .

3.4 新版功能.

在 3.7 版更改: 引发 ModuleNotFoundError 而不是 AttributeError 如果 包裹 实际上不是一个包裹(即缺少 __path__ 属性)。

importlib.util.module_from_spec(spec)

基于创建新模块 specspec.loader.create_module .

如果 spec.loader.create_module 不返 None ,则不会重置任何预先存在的属性。同样,没有 AttributeError 如果在访问时触发,将引发 spec 或者在模块上设置属性。

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

3.5 新版功能.

@importlib.util.module_for_loader

A decorator 对于 importlib.abc.Loader.load_module() 处理选择要加载的适当模块对象。修饰方法应该有一个调用签名,它采用两个位置参数(例如 load_module(self, module) )第二个参数是模块 object 供加载器使用。请注意,由于假设有两个参数,装饰器将不在静态方法上工作。

装饰方法将采用 name 将按预期加载的模块的 loader . 如果在 sys.modules 然后建造一个新的。不管模块来自何处, __loader__ 设置为 self__package__ 是根据什么设置的 importlib.abc.InspectLoader.is_package() 返回(如果可用)。这些属性被无条件地设置为支持重新加载。

如果修饰方法引发异常并向添加模块 sys.modules ,然后移除模块,以防止部分初始化的模块留在 sys.modules . 如果模块已经在 sys.modules 然后就让它一个人呆着。

在 3.3 版更改: __loader____package__ 自动设置(如果可能)。

在 3.4 版更改: 集合 __name____loader__ __package__ 无条件支持重新加载。

3.4 版后已移除: 导入机制现在直接执行此功能提供的所有功能。

@importlib.util.set_loader

A decorator 对于 importlib.abc.Loader.load_module() 设置 __loader__ 返回模块的属性。如果属性已经设置,则装饰器不执行任何操作。假定封装方法的第一个位置参数(即 self 是什么? __loader__ 应设置为。

在 3.4 版更改: 集合 __loader__ 如果设置为 None ,就好像属性不存在一样。

3.4 版后已移除: 输入机器会自动处理这个问题。

@importlib.util.set_package

A decorator 对于 importlib.abc.Loader.load_module() 设置 __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 新版功能.

在 3.6 版更改: 接受一 path-like object .

importlib.util.source_hash(source_bytes)

返回的hash值 source_bytes 作为字节。基于hash的 .pyc 文件嵌入 source_hash() 对应源文件头中的内容。

3.7 新版功能.

class importlib.util.LazyLoader(loader)

一个类,它将模块的装入程序的执行推迟到模块具有访问属性为止。

这个类 only 与定义 exec_module() 需要控制模块使用的模块类型。出于同样的原因,加载器的 create_module() 方法必须返回 None 或其类型 __class__ 属性可以随不使用而改变 slots . 最后,模块替换放置在 sys.modules 无法正常工作,因为无法安全地替换整个解释器中的模块引用; ValueError 如果检测到此类替换,则引发。

注解

对于启动时间至关重要的项目,此类允许在从不使用模块的情况下将加载模块的成本降至最低。对于启动时间不重要的项目,则使用此类 沉重地 由于在加载过程中创建的错误消息被延迟,因而出现在上下文之外,因此不鼓励使用。

3.5 新版功能.

在 3.6 版更改: 开始调用 create_module() ,正在删除的兼容性警告 importlib.machinery.BuiltinImporterimportlib.machinery.ExtensionFileLoader .

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))

实例

以编程方式导入

要以编程方式导入模块,请使用 importlib.import_module() . ::

import importlib

itertools = importlib.import_module('itertools')

检查模块是否可以导入

如果您需要确定一个模块是否可以在不进行实际导入的情况下导入,那么您应该使用 importlib.util.find_spec() . ::

import importlib.util
import sys

# For illustrative purposes.
name = 'itertools'

if name in sys.modules:
    print(f"{name!r} already in sys.modules")
elif (spec := importlib.util.find_spec(name)) is not None:
    # If you chose to perform the actual import ...
    module = importlib.util.module_from_spec(spec)
    sys.modules[name] = module
    spec.loader.exec_module(module)
    print(f"{name!r} has been imported")
else:
    print(f"can't find the {name!r} module")

直接导入源文件

要直接导入python源文件,请使用以下方法(仅限python 3.5和更新版本)::

import importlib.util
import sys

# For illustrative purposes.
import tokenize
file_path = tokenize.__file__
module_name = tokenize.__name__

spec = importlib.util.spec_from_file_location(module_name, file_path)
module = importlib.util.module_from_spec(spec)
sys.modules[module_name] = module
spec.loader.exec_module(module)

实现惰性导入

下面的示例演示如何实现延迟导入:

>>> import importlib.util
>>> import sys
>>> def lazy_import(name):
...     spec = importlib.util.find_spec(name)
...     loader = importlib.util.LazyLoader(spec.loader)
...     spec.loader = loader
...     module = importlib.util.module_from_spec(spec)
...     sys.modules[name] = module
...     loader.exec_module(module)
...     return module
...
>>> lazy_typing = lazy_import("typing")
>>> #lazy_typing is a real module object,
>>> #but it is not loaded in memory yet.
>>> lazy_typing.TYPE_CHECKING
False

设置导入程序

对于导入的深度自定义,您通常希望实现 importer .这意味着管理 finderloader 事情的另一面。对于寻找者来说,根据你的需要,有两种口味可供选择:a meta path finder 或A path entry finder .前者是你要穿的 sys.meta_path 后者是您使用 path entry hooksys.path_hooks 它与 sys.path 可能创建查找器的条目。此示例将向您展示如何注册您自己的导入程序,以便导入使用它们(为了自己创建导入程序,请阅读此包中定义的适当类的文档)::

import importlib.machinery
import sys

# For illustrative purposes only.
SpamMetaPathFinder = importlib.machinery.PathFinder
SpamPathEntryFinder = importlib.machinery.FileFinder
loader_details = (importlib.machinery.SourceFileLoader,
                  importlib.machinery.SOURCE_SUFFIXES)

# Setting up a meta path finder.
# Make sure to put the finder in the proper location in the list in terms of
# priority.
sys.meta_path.append(SpamMetaPathFinder)

# Setting up a path entry finder.
# Make sure to put the path hook in the proper location in the list in terms
# of priority.
sys.path_hooks.append(SpamPathEntryFinder.path_hook(loader_details))

逼近 importlib.import_module()

import本身是在python代码中实现的,这使得通过importlib公开大多数导入机制成为可能。下面通过提供importlib公开的各种API的近似实现来帮助说明 importlib.import_module() (python 3.4及更高版本用于importlib,python 3.6及更高版本用于代码的其他部分)。::

import importlib.util
import sys

def import_module(name, package=None):
    """An approximate implementation of import."""
    absolute_name = importlib.util.resolve_name(name, package)
    try:
        return sys.modules[absolute_name]
    except KeyError:
        pass

    path = None
    if '.' in absolute_name:
        parent_name, _, child_name = absolute_name.rpartition('.')
        parent_module = import_module(parent_name)
        path = parent_module.__spec__.submodule_search_locations
    for finder in sys.meta_path:
        spec = finder.find_spec(absolute_name, path)
        if spec is not None:
            break
    else:
        msg = f'No module named {absolute_name!r}'
        raise ModuleNotFoundError(msg, name=absolute_name)
    module = importlib.util.module_from_spec(spec)
    sys.modules[absolute_name] = module
    spec.loader.exec_module(module)
    if path is not None:
        setattr(parent_module, child_name, module)
    return module