python - "del sys.modules[module]"实际上是做什么的?

标签 python module sys python-internals

众所周知,您可以执行del sys.modules[module] 来删除导入的模块。所以我在想:这与重写 sys.modules 有什么不同?一个有趣的事实是,重写 sys.modules 并不能真正删除模块。

# 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 imported,这意味着a_module 已成功删除。

我的问题是:除了更改字典之外,del sys.modules[module] 实际上做了什么?

最佳答案

sys.modulesPython 可访问的引用,用于跟踪导入了哪些模块的规范 数据结构。从该字典中删除一个名称意味着以后任何导入该模块的尝试都将导致 Python 从头开始​​加载该模块。

换句话说,每当您使用import 语句时,Python 做的第一件事就是检查sys.modules 引用的字典是否已经包含该模块的条目并继续下一步(在当前命名空间中绑定(bind)名称)而不先加载模块。如果您从 sys.modules 中删除条目,则 Python 将找不到已加载的模块并再次加载。

请注意此处关于 Python 可访问 的谨慎措辞。实际的字典存在于 Python 堆中,sys.modules 只是对它的一个引用。您通过分配给 sys.modules替换该引用为另一个字典。但是,解释器对其有更多引用;它们只是无法从 Python 代码访问,而不是没有 ctypes 技巧来访问 C-API。

注意这是explicitly documented :

However, replacing the dictionary will not necessarily work as expected and deleting essential items from the dictionary may cause Python to fail.

从 C-API 中,您必须使用 PyThreadState_Get()->interp->modules 来获取对字典的内部引用。

关于python - "del sys.modules[module]"实际上是做什么的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43181440/

相关文章:

javascript - 关于 Nodejs 模块的错误

linux - 如何降低 Linux 中 Rails 3 命令的用户时间与系统时间的比率

python - xbbg 的 BBG_ROOT(简化的 blpapi 包)

python - 如何完成 sys.stdin.readlines() 输入?

python - 使 Python unittest 显示 AssertionError 但没有 Traceback

python - 使用Python将信息存储在MySQL数据库中

java - 如何确定数字是以 .5 还是 .0 结尾

python - scikit-learn 中 predict 与 predict_proba 的区别

Python MySQL 连接器偶尔无法插入/更新

module - Lua 全局变量包含当前文件的路径?