Python 为什么sys.modules中有虚拟模块?
导入标准“日志记录”模块会用一堆伪条目污染sys.modules:Python 为什么sys.modules中有虚拟模块?,python,import,Python,Import,导入标准“日志记录”模块会用一堆伪条目污染sys.modules: Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on win32 >>> import sys >>> import logging >>> sorted(x for x in sys.modules.keys() if 'log' in x) ['logging', '
Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on win32
>>> import sys
>>> import logging
>>> sorted(x for x in sys.modules.keys() if 'log' in x)
['logging', 'logging.atexit', 'logging.cStringIO', 'logging.codecs',
'logging.os', 'logging.string', 'logging.sys', 'logging.thread',
'logging.threading', 'logging.time', 'logging.traceback', 'logging.types']
# and perhaps even more surprising:
>>> import traceback
>>> traceback is sys.modules['logging.traceback']
False
>>> sys.modules['logging.traceback'] is None
True
所以导入这个包会在sys.modules中添加额外的名称,只是它们不是模块,只是引用None。其他模块(例如xml.dom和编码)也有这个问题。为什么?
编辑:根据bobince的回答,有一些页面描述了(请参阅“sys.modules中的虚拟条目”一节)和该功能。
sys.modules
中的无值是相对查找的缓存失败
因此,当您在包foo
中导入sys时,Python会首先查找foo.sys
模块,如果失败,将转到顶级sys
模块。为了避免在进一步的相对导入时再次检查文件系统的foo/sys.py
,它将None
存储在sys.modules
中,以标记该模块不存在,后续导入不应再查看该模块,而是直接转到加载的sys
这是一个cPython实现细节,你不能有效地依赖它,但如果你正在进行令人讨厌的魔法导入/重新加载黑客攻击,你需要知道它
它发生在所有包上,而不仅仅是日志记录
。例如,import xml.dom
,当它试图从xml.dom
内部导入xml
时,请参见模块列表中的xml.dom.xml
随着Python朝着绝对导入的方向发展,这种丑恶的情况将更少发生。谢谢!我在我的问题中添加了背景中的链接,并引用了,如果它“发生在所有包中”,为什么我从来没有在我自己的东西中看到过?我希望看到“mymodule.sys”、“mymodule.os”等等,周围有几十个这样的虚拟模块,但只看到一些,比如xml.dom、日志和编码(正如d.Shawley提到的),这发生在我的包上。但是只有包,而不是简单的模块。奇怪。我非常确定,过去为了各种调试目的,我经常检查sys.modules,但没有注意到sys.modules中引用的几十个stdlib模块是我的子包下的虚拟模块。然而,它们确实存在,例如,像“xxx.xxx.sys”这样的东西出现了16次。。。事实上,我以前在任何地方都没有发现这一点。显然,出于某种原因,我没有寻找明显的标题“说Neeeow…Wum…Ping的骑士”。啊,Python…我要发布一个完全相同的副本-我今天的第二个副本:P