1️⃣ 基本行为
importlib.reload(module) 的作用:
重新执行模块的 顶层代码(即模块文件中的所有语句)。
返回模块对象本身(与原来的模块对象同一个引用)。
不会重新创建模块对象,所以原来的模块引用仍然有效。
import mymodule
import importlib
mymodule.x = 10
importlib.reload(mymodule)
print(mymodule.x) # x 的值可能不是 10,而是模块重新执行后的默认值
2️⃣ 模块状态的微妙影响
(a)模块变量
模块中的全局变量会被重新赋值,但 对象引用不会更新原来的引用。
# mymodule.py
mylist = []
def add_item(item):
mylist.append(item)
import mymodule
import importlib
myl = mymodule.mylist
mymodule.add_item(1)
print(myl) # [1]
importlib.reload(mymodule)
print(myl) # [] ?
为什么?
importlib.reload 会重新执行模块,创建一个新的 mylist = [] 对象,并赋值给 mymodule.mylist。
但是你原来绑定的 myl 还是指向旧列表对象,所以 myl 不会被刷新。
结论:模块重新加载不会自动刷新外部持有的引用。
(b)函数和类对象
函数和类也会被重新定义:
# mymodule.py
def greet():
print("Hello v1")
import mymodule
mymodule.greet() # Hello v1
importlib.reload(mymodule)
mymodule.greet() # Hello v1(如果修改了源码,就会变)
但是注意:
old_greet = mymodule.greet
importlib.reload(mymodule)
old_greet() # 调用的还是旧版本函数
结论:已经引用的函数、类对象不会自动更新,只有模块命名空间中的名字被更新。
(c)子模块和导入别名
# package/__init__.py
from . import submodule
# main.py
import package.submodule as sm
import importlib
importlib.reload(package)
sm.func() # 可能还是旧版本
原因:importlib.reload(package) 只重新加载 package,不会自动 reload submodule。外部别名仍然指向旧模块对象。
(d)单例对象和状态
如果模块创建了单例对象,reload 会创建新的对象,但原来的对象仍存在。
# mymodule.py
singleton = {}
# main.py
import mymodule
s1 = mymodule.singleton
importlib.reload(mymodule)
s2 = mymodule.singleton
print(s1 is s2) # False
3️⃣ 实际经验和注意事项
不要指望 reload 会“完全重置状态”,它只是重新执行模块代码。
外部持有的引用不会自动更新。
类和函数重新加载后,旧实例不会升级到新类。
对于复杂的依赖关系,reload 很容易导致状态不一致。
最保险的方式:reload 前手动清理引用,或尽量用 importlib.reload 在交互式调试中使用,而不是生产环境。
💡 调试小技巧:
import sys, importlib
print(id(sys.modules['mymodule']))
importlib.reload(sys.modules['mymodule'])
print(id(sys.modules['mymodule'])) # 同一个对象,但内部变量可能改变
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70050070/viewspace-3171777/ ,如需转载,请注明出处,否则将追究法律责任。