importlib
包的目的是双重的。一个是在Python源代码中提供import
语句(以及扩展名为__import__()
函数)的实现。这提供了可以移植到任何Python解释器的import
的实现。这也提供了比在除了Python之外的编程语言中实现的实现更容易理解的实现。
第二个目的是,实现import
的组件在此包中公开,使用户更容易创建自己的自定义对象(通常称为importer)以参与导入处理。
-
内建
__import__()
函数的实现。注意
程序化导入模块应使用
import_module()
而不是此函数。
importlib.
__import__
(name,globals=None, locals=None, fromlist=(), level=0)¶
-
导入模块。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.
import_module
(name,package=None)¶
-
找到模块的加载器,可选择在指定的路径中。如果模块在
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.
find_loader
(name,path=None)¶
-
使存储在
sys.meta_path
的finder的内部缓存无效。如果finder实现invalidate_caches()
,那么它将被调用以执行无效。如果在程序运行时创建/安装了任何模块,则应调用此函数,以确保所有查找程序都注意到新模块的存在。版本3.3中的新功能。
importlib.
invalidate_caches
()¶
-
重新载入先前导入的模块。参数必须是一个模块对象,因此必须先被成功导入。如果您已使用外部编辑器编辑了模块源文件,并希望在不离开Python解释器的情况下尝试新版本,这将非常有用。返回值是模块对象(如果重新导入会导致将不同的对象放置在
sys.modules
中,则可能不同)。当执行
reload()
时:- Python模块的代码被重新编译并重新执行模块级代码,通过重用最初加载模块的loader来定义一组新的对象,这些对象被绑定到模块字典中的名称。扩展模块的
init
功能不再第二次调用。 - 与Python中的所有其他对象一样,旧对象只有在引用计数下降到零后才被回收。
- 模块命名空间中的名称将更新为指向任何新的或已更改的对象。
- 对旧对象的其他引用(例如模块外部的名称)不会重新引用来引用新对象,如果需要,必须在每个命名空间中对其进行更新。
还有一些其他警告:
当模块被重新加载时,它的字典(包含模块的全局变量)被保留。名称的重定义将覆盖旧的定义,因此这通常不是问题。如果模块的新版本未定义由旧版本定义的名称,则旧定义将保留。如果它维护一个全局表或对象缓存,使用
try
语句可以测试表的存在并跳过其初始化,如果需要,这个特性可以用于模块的优势:try: cache except NameError: cache = {}
重新加载内建或动态加载的模块通常不是很有用。不建议重新加载
sys
,__main__
,builtins
和其他关键模块。在许多情况下,扩展模块不会被设计为初始化多次,并且可能在重新加载时以任意方式失败。如果模块使用
from
...import
...从另一个模块导入对象,则对其他模块调用reload()
其中一个方法是重新执行from
语句,另一个方法是使用import
和限定名称(module.name t15>)。如果一个模块实例化一个类的实例,重新加载定义该类的模块不会影响实例的方法定义 - 它们继续使用旧的类定义。对于派生类同样如此。
版本3.4中的新功能。
- Python模块的代码被重新编译并重新执行模块级代码,通过重用最初加载模块的loader来定义一组新的对象,这些对象被绑定到模块字典中的名称。扩展模块的
importlib.
reload
(module)¶