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

标签 python python-3.x python-import

我在寻找another question的答案时尝试设置字典sys.modules并发现了一些有趣的事情。链接的问题涉及消除导入模块的所有影响。基于another post ,我提出了在导入后从 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 。尽管 import 语句没有引发错误并且似乎成功完成(即 numpy > 模块存在于本地命名空间中)。

另一方面,我在 my answer 中所做的实现链接的问题似乎确实工作正常。它直接修改字典而不是交换它:

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 的另一个引用,并使用该内部引用,无论我对公共(public)一.但我不确定这是否涵盖了所有内容,所以我想知道到底发生了什么。

最佳答案

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

sys.modules 并非旨在被替换。 docs提到替换它可能会出现意想不到的行为:

This can be manipulated to force reloading of modules and other tricks. However, replacing the dictionary will not necessarily work as expected and deleting essential items from the dictionary may cause Python to fail.

关于Python 换出 sys.modules 并不像直觉那样工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42142660/

相关文章:

python - 在 Python 中查看变量

python - Pandas 哈希表 KeyError

python 生成具有特定条件的无限列表

Python - 数据模型 - 子类与实例

python - 访问对象的对象属性数组会在 python 中给出属性错误

python - 如何在 mongoengine 中使用有序 false 进行批量插入

python - 如何借助数据透视表填充 NaN 值?

python - 如何在我的 python 脚本中包含第 3 方模块?

python - 构建适用于测试和运行代码的 python3 代码和导入的正确方法是什么?

python - 如何在不初始化 GPU 的情况下使我的包可导入