gpt4 book ai didi

python - 重新加载功能无法删除已删除的变量

转载 作者:行者123 更新时间:2023-12-03 21:20:35 25 4
gpt4 key购买 nike

我正在尝试从正在修改的模块中访问变量,而主脚本通过使用重新加载运行。但是 reload 函数无法删除已从模块中删除的变量。如何强制 python 删除它们?

这是我的代码

我的 module.py :

a = 1
b = 2

我的主要 scipt.py :
import time
from importlib import reload

import module

while True:
reload(module)
print('------- module reloaded')
try:
print('a: ', module.a)
except AttributeError:
print('a: ', 'undefined')
try:
print('b: ', module.b)
except AttributeError:
print('b: ', 'undefined')
try:
print('c: ', module.c)
except AttributeError:
print('c: ', 'undefined')

time.sleep(5)

正如预期的那样,如果我用 python (3.5.1) 运行我的脚本,我会得到输出:
------- module reloaded
a: 1
b: 2
c: undefined

但是当我将 module.py 更改如下时,我得到了一个意外的行为:
# a = 1
b = 3
c = 4

我有以下输出:
------- module reloaded
a: 1
b: 3
c: 4

这意味着重新加载正确地更新了 b 的值并添加了新变量 c。但它未能删除已从模块中删除的变量 a。它似乎只对新版本模块中的变量执行更新。如何强制重新加载功能删除删除的值?

感谢您的帮助

最佳答案

这里的问题是 reload用大约 exec 的代码实现s 现有缓存模块命名空间中模块代码的当前版本。这样做的原因是 reload旨在产生全局影响; reload(module)它不仅会为您重新加载它,它还会更改每个其他模块的个人导入的 module 副本.如果它创建了一个新的模块命名空间,其他模块仍然会缓存旧模块;同时删除 exec 之前的旧模块的内容ing 可能会有所帮助,它可能会破坏已经导入的包子模块,触发竞争条件(线程可能会在 module.a 之前和之后看到 reload ,但它会在 reload 期间神秘地消失一会儿),等等
the docs note :

When a module is reloaded, its dictionary (containing the module’s global variables) is retained. Redefinitions of names will override the old definitions, so this is generally not a problem. If the new version of a module does not define a name that was defined by the old version, the old definition remains.


如果您绝对必须这样做,有一些解决方法可以绕过此安全机制。最简单的方法是从模块缓存中删除模块并重新导入,而不是 reload把它:
import sys  # At top of file

del sys.modules['module']
import module
这不会更新该模块的任何其他导入器(它们将保留过时的缓存),但如果该模块仅在您的模块中使用,那将起作用。
另一种可能有效的方法(未经测试,有点疯狂)是在 reload 之前从模块中显式删除所有公共(public)名称。使用类似的东西:
# Intentionally done as list comprehension so no modification to module's globals dict
# occurs while we're iterating it
# Might make sense to use dir or iterate module.__all__ if available instead of using vars;
# depends on design
for name in [n for n in vars(module) if not n.startswith('_')]:
try:
delattr(module, name)
except Exception:
pass # Undeletable attribute for whatever reason, just ignore and let reload deal with it
reload(module) # Now exec occurs in clean namespace
这将避免陈旧的缓存问题,以换取精神错乱。
真的,答案是“不要使用依赖于生产的设计 reload ing”;如果模块只是数据,则将其存储为 JSON 文件或类似文件,然后重新解析它(这通常比 Python 导入机制导入模块所经历的要便宜得多)。

关于python - 重新加载功能无法删除已删除的变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58946837/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com