2009-12-24 30 views
17

導入標準的「日誌」模塊污染sys.modules來了一堆假的條目:爲什麼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中,只是他們不模塊,只是沒有引用。其他模塊(例如xml.dom和編碼)也有這個問題。爲什麼?

編輯:上bobince的回答大廈,也有描述the origin頁面(請參見「sys.modules中虛擬條目」)和功能的future

+0

良好的聯繫...我沒有真正發現這是記錄在任何地方之前。很明顯,出於某種原因,我沒有尋找明顯的標題「誰說Neeeow ... Wum ... Ping的騎士」。啊,Python ... – bobince 2009-12-24 17:01:51

+1

我打算髮佈一個確切的副本 - 今天我的第二個:P – 2017-01-23 17:30:50

回答

23

Nonesys.modules中的值是相對查找的高速緩存失敗。

所以,當你在包foo和你import sys,Python的首先查找一個foo.sys模塊,如果失敗轉到頂級sys模塊。爲避免在進一步相對導入時再次檢查文件系統foo/sys.py,它將None存儲在sys.modules中,以標記模塊不存在,並且隨後的導入不應該再次出現,但直接轉到加載的sys

這是一個你不能有效依賴的cPython實現細節,但是如果你正在進行惡意的魔術導入/重載黑客攻擊,你將需要知道它。

它發生在所有包裹,而不僅僅是logging。例如,import xml.dom並在模塊列表中看到xml.dom.xml,因爲它試圖從xml.dom內部導入xml

隨着Python走向絕對的進口,這種醜陋將會發生得更少。

+0

謝謝!我在我的問題中添加了鏈接,並將其引用到http://www.python.org/dev/peps/pep-0328 – 2009-12-24 15:39:17

+0

如果它「發生在所有包上」,爲什麼我從來沒有見過這種情況東東?我期望看到「mymodule.sys」,「mymodule.os」等幾十個和幾十個這樣的虛擬模塊,但只能看到它有一些像xml.dom,日誌記錄和編碼(如D.Shawley提到)。 – 2009-12-24 15:47:11

+0

它發生在我的包裹上。但只有包,而不是簡單的模塊。 – bobince 2009-12-24 15:56:32

0

我不知道爲什麼會發生,但encodings展示與None相同的參考。

Python 2.6.2 (r262:71600, May 24 2009, 00:12:54) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import sys 
>>> for n in filter(lambda x: x.startswith('encodings'), sys.modules): 
... print n, type(sys.modules[n]) 
... 
encodings <type 'module'> 
encodings.encodings <type 'NoneType'> 
encodings.codecs <type 'NoneType'> 
encodings.__builtin__ <type 'NoneType'> 
encodings.utf_8 <type 'module'> 
encodings.aliases <type 'module'> 

我真的不知道是怎麼回事了一些條目爲None,但我可以說,這是不是唯一的logging模塊。

相關問題