【问题标题】:Why are there dummy modules in sys.modules?为什么 sys.modules 中有虚拟模块?
【发布时间】:2010-12-29 19:52:15
【问题描述】:

导入标准的“日志”模块会用一堆虚拟条目污染 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', '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 的回答,有页面描述了 the origin(参见“sys.modules 中的虚拟条目”部分)和 future 的功能。

【问题讨论】:

  • 很好的链接...我实际上并没有发现这在任何地方都有记录。显然出于某种原因,我没有搜索明显的标题“说 Neeeow ... Wum ... Ping 的骑士”。啊,Python……
  • 我要发布一个完全相同的副本 - 我今天的第二个:P

标签: python import


【解决方案1】:

sys.modules 中的None 值是相对查找的缓存失败。

因此,当您在包fooimport sys 中时,Python 会首先查找foo.sys 模块,如果失败则转到顶级sys 模块。为了避免在进一步的相关导入时再次检查文件系统中的foo/sys.py,它将None 存储在sys.modules 中以标记模块不存在并且后续导入不应再查看那里,而是直接进行到已加载的sys

这是一个您无法有效依赖的 cPython 实现细节,但如果您正在执行令人讨厌的魔术导入/重新加载黑客攻击,则需要知道它。

它发生在所有包上,而不仅仅是logging。例如,import xml.dom 并在模块列表中看到 xml.dom.xml,因为它尝试从 xml.dom 内部导入 xml

随着 Python 朝着绝对导入的方向发展,这种丑陋的事情会减少。

【讨论】:

  • 谢谢!我在问题中添加了指向背景的链接,并由python.org/dev/peps/pep-0328 引用
  • 如果它“发生在所有包上”,为什么我从来没有在我自己的东西上看到过这种情况?我希望看到“mymodule.sys”、“mymodule.os”等等,周围有几十个这样的虚拟模块,但只看到一些像 xml.dom、日志记录和编码(如 D.Shawley提及)。
  • 这发生在我的包裹上。但只有包,而不是简单的模块。
  • 奇怪。我确定我过去经常检查 sys.modules 用于各种调试目的,而没有注意到 sys.modules 中引用的数十个 stdlib 模块作为我的子包下的虚拟模块。然而它们确实存在,例如,“xxx.xxx.sys”之类的内容出现了 16 次。
猜你喜欢
  • 2017-07-07
  • 2010-09-26
  • 1970-01-01
  • 2019-03-03
  • 2017-09-11
  • 2018-01-24
  • 1970-01-01
相关资源
最近更新 更多