问题描述
众所周知,您可以执行 del sys.modules[module]
删除导入的模块.所以我在想:这与重写 sys.modules
有什么不同?一个有趣的事实是,重写 sys.modules
并不能真正删除一个模块.
As everyone knows, you can do del sys.modules[module]
to delete an imported module. So I was thinking: how is this different from rewriting sys.modules
? An interesting fact is, rewriting sys.modules
can't truely delete a module.
# a_module.py
print("a module imported")
然后
import sys
def func1():
import a_module
# del sys.modules['a_module']
sys.modules = {
k: v for k, v in sys.modules.items() if 'a_module' not in k}
print('a_module' not in sys.modules) # True
def func2():
import a_module
func1() # a module imported
func2() # no output here
如果我使用 del sys.modules['a_module']
,调用 func2()
也会打印 a module import
,这意味着a_module
删除成功.
If I use del sys.modules['a_module']
, calling func2()
also prints a module imported
, which implies that a_module
is successfully deleted.
我的问题是:除了改变字典之外,del sys.modules[module]
实际上做了什么?
My question is: What does del sys.modules[module]
actually do, besides changing the dictionary?
推荐答案
sys.modules
是 Python 可访问的参考规范用于跟踪导入哪些模块的数据结构.从该字典中删除名称意味着以后任何导入模块的尝试都将导致 Python 从头开始加载模块.
sys.modules
is the Python-accessible reference to the canonical data structure for tracking what modules are imported. Removing a name from that dictionary means that any future attempts to import the module will result in Python loading the module from scratch.
换句话说,每当你使用 import
语句时,Python 做的第一件事就是检查 sys.modules
引用的字典是否已经有该模块的条目并继续下一步(在当前命名空间中绑定名称)而不先加载模块.如果您从 sys.modules
中删除条目,那么 Python 将找不到已加载的模块并再次加载.
In other words, whenever you use an import
statement, the first thing Python does is check if the dictionary that sys.modules
references already has an entry for that module and proceed with the next step (binding names in the current namespace) without loading the module first. If you delete entries from sys.modules
, then Python won't find the already-loaded module and loads again.
请注意此处关于 Python 可访问 的谨慎措辞.实际的字典存在于 Python 堆中,sys.modules
只是对它的一个引用.您通过分配给 sys.modules
,用另一个字典替换了该引用.然而,解释器有更多的引用;它们只是无法从 Python 代码访问,无论如何都无法通过 ctypes
技巧访问 C-API.
Note the careful wording about Python-accessible here. The actual dictionary lives on the Python heap and sys.modules
is just one reference to it. You replaced that reference with another dictionary by assigning to sys.modules
. However, the interpreter has more references to it; they just are not accessible from Python code, not without ctypes
trickery to access the C-API anyway.
请注意,这是明确记录的:
Note that this is explicitly documented:
但是,替换字典不一定能按预期工作,从字典中删除必要的项目可能会导致 Python 失败.
从 C-API 中,您必须使用 PyThreadState_Get()->interp->modules
来获取对字典的内部引用.
From the C-API, you'd have to use PyThreadState_Get()->interp->modules
to get the internal reference to the dictionary.
这篇关于“del sys.modules[module]"是什么意思?其实呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!