重新加载一个之前导入过的 module。参数必须是一个模块对象,因此它必须是之前成功导入过的。如果你用外部编辑器编辑了模块源文件,并想在不离开 Python 解释器的情况下尝试新版本,这会很有用。返回值是模块对象(如果重新导入导致不同的对象被放入 sys.modules,则可能不同)。
当 reload() 被执行时:
Python 模块的代码会被重新编译,模块级的代码会重新执行,通过重用最初加载该模块的 loader(加载器),定义了一组新的对象并绑定到模块字典中的名称。扩展模块的 init 函数不会被第二次调用。
与 Python 中所有其他对象一样,旧对象只有在它们的引用计数降为零后才会被回收。
模块命名空间中的名称会更新以指向任何新的或更改的对象。
对旧对象的其他引用(例如模块外部的名称)不会被重新绑定以引用新对象,如果需要,必须在它们出现的每个命名空间中进行更新。
还有一些其他注意事项:
当一个模块被重新加载时,它的字典(包含模块的全局变量)会被保留。名称的重新定义将覆盖旧的定义,所以这通常不是问题。如果模块的新版本没有定义旧版本中定义的名称,那么旧的定义仍然存在。如果模块维护一个全局表或对象缓存,这个特性可以被模块利用——通过 try 语句,它可以测试表是否存在,如果需要可以跳过其初始化。
try:
cache
except NameError:
cache = {}
重新加载内置或动态加载的模块通常不是很有用。不建议重新加载 sys、__main__、builtins 和其他关键模块。在许多情况下,扩展模块的设计不是为了被初始化多次,并且在重新加载时可能会以任意方式失败。
如果一个模块使用 from … import … 从另一个模块导入对象,为另一个模块调用 reload() 并不会重新定义从它导入的对象——一种解决方法是重新执行 from 语句,另一种是使用 import 和限定名称(module.name)。
如果一个模块实例化了一个类的实例,重新加载定义该类的模块不会影响实例的方法定义——它们继续使用旧的类定义。对于派生类也是如此。
在 3.4 版本加入。
在 3.7 版更改: 当被重新加载的模块缺少 ModuleSpec 时,会引发 ModuleNotFoundError。
警告
此函数非线程安全。从多个线程调用它可能导致未预期的行为。建议使用 threading.Lock 或其他同步原语来实现线程安全的模块重载。