Python 更改sys.modules导致意外的键错误

Python 更改sys.modules导致意外的键错误,python,Python,大型系统中的一些自动测试需要能够导入模块,然后将sys.modules恢复到其原始状态 但是这个代码片段: import sys sys.modules = dict(sys.modules) import pickle 在Python 3.6-3.8中导致此keyrerror: Traceback (most recent call last): File "<stdin>", line 1, in <module> File "[...]/python3.

大型系统中的一些自动测试需要能够导入模块,然后将
sys.modules
恢复到其原始状态

但是这个代码片段:

import sys

sys.modules = dict(sys.modules)
import pickle
在Python 3.6-3.8中导致此
keyrerror

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "[...]/python3.6/pickle.py", line 1562, in <module>
    from _pickle import (
KeyError: '_compat_pickle'
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“[…]/python3.6/pickle.py”,第1562行,在
从腌菜进口(
KeyError:“\u compat\u pickle”
似乎只有
pickle
和依赖于它的模块(如
多处理
)受到了影响。我已经调查了
\u compat\u pickle
——它是一个与Python 2兼容的模块——但没有什么会导致这种情况


是否有安全的方法将系统模块恢复到早期状态?这种意外的按键错误背后的机制是什么?

问题是系统模块是个谎言(我认为)。它实际上不是当前解释器中存储在C级别的模块dict的真正源,并且
sys.modules
只是它的一个副本。
\u pickle
是特殊的,因为它从C源导入模块,我认为这会导致此错误(导入的
tstate->interp->modules
所述内容与导入的
sys.modules
所认为的内容不匹配)

这可能被认为是python中的错误。我不确定是否已经存在错误报告。以下是错误报告:


您可以在代码前后保存模块中的键,然后删除所有其他条目。

我无法在ubuntuI上用Python 3.6.9重现此错误。UI可以在windows上用3.7.0重现此错误。(或类似错误,取决于导入的内容)您是否尝试过使用
sys.modules.copy()
而不是调用
dict
?您的描述说您想还原
系统模块,但实际上您替换了它。您是否尝试过实际调整原始
系统模块的内容?@MisterMiyagi:事实上,这是我在实际代码中使用的解决方案,但它让我感到紧张,因为我没有guar你的答案很有说服力,但是如果我只在sys.modules上使用字典操作,是否可以保证一切都会正常?是的。这是一本字典,只是存储在多个位置。因此,你可能是对的,这是一个bug-你根本不应该被允许分配给sys.modules。我将接受一个测试看看它是否在那里,如果不在就归档。看,看,有人出于同样的原因碰到了相同的错误!我已经在想‘应该有一个错误报告’,但没有搜索足够长的时间来找到它。