当前位置: 代码迷 >> python >> Python 换出 sys.modules 并不像直觉那样工作
  详细解决方案

Python 换出 sys.modules 并不像直觉那样工作

热度:137   发布时间:2023-06-13 14:18:59.0

我正在尝试设置字典sys.modules在回答时遇到了一些有趣的事情。 链接的问题涉及消除导入模块的所有影响。 基于,我想出了在导入后从sys.modules中删除所有新模块的想法。 我最初的实现是执行以下操作(使用numpy作为加载和卸载的模块进行测试):

# Load the module
import sys
mod_copy = sys.modules.copy()
print('numpy' in mod_copy, 'numpy' in sys.modules) # False False
import numpy
print('numpy' in mod_copy, 'numpy' in sys.modules) # False True
print(id(numpy)) # 45138472

打印输出显示 numpy 已成功导入,并且浅拷贝不包含它,正如预期的那样。

现在我的想法是通过将mod_copy交换回sys.modules来卸载模块,然后删除对模块的本地引用。 从理论上讲,这应该删除对它的所有引用(可能确实如此):

sys.modules = mod_copy
del numpy
print('numpy' in sys.modules) # False

这应该足以能够重新导入模块,但是当我这样做时

import numpy
print('numpy' in sys.modules) # False
print(id(numpy)) # 45138472

numpy 模块似乎没有重新加载,因为它具有与以前相同的id 它没有出现在sys.modules ,尽管import语句没有引发错误并且似乎成功完成(即,本地命名空间中存在一个numpy模块)。

在另一方面,我在做执行对链接的问题确实出现了做工精细。 它直接修改字典而不是将其换出:

import sys
mod_copy = sys.modules.copy()
print('numpy' in mod_copy, 'numpy' in sys.modules) # False False
import numpy
print('numpy' in mod_copy, 'numpy' in sys.modules) # False True
print(id(numpy)) # 35963432

for m in list(sys.modules):
    if m not in mod_copy:
        del sys.modules[m]
del numpy
print('numpy' in sys.modules) # False

import numpy
print('numpy' in sys.modules) # True
print(id(numpy)) # (54941000 != 35963432)

我在 Anaconda 安装上使用 Python 3.5.2。 我对专注于 Python 3 的解释最感兴趣,但我对 Python 2.7+ 也很好奇。

我能想到的唯一一件事就是sys维护对sys.modules另一个引用,并使用该内部引用,而不管我对公共引用做什么。 我不确定这是否涵盖了所有内容,所以我想知道到底发生了什么。

即使在 Python 3.5 中,导入实现的一部分,这部分使用PyThreadState_GET()->interp->modules来检索模块缓存,而不是通过sys.modules属性。 您的导入是通过这些代码路径之一在旧的sys.modules找到numpy

sys.modules不是为了替换而设计的。 提到替换它可能会出现意外行为:

这可以被操纵以强制重新加载模块和其他技巧。 但是,替换字典不一定会按预期工作,并且从字典中删除重要项目可能会导致 Python 失败。

  相关解决方案