2009-12-24 2 views
17

Импорт модуля «Logging» стандартного загрязняет 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, за исключением того, что они не являются модулями, только ссылки на None , У других модулей (например, xml.dom и encodings) есть эта проблема. Зачем?

Edit: Опираясь на ответ bobince, есть страницы, описывающие the origin (смотрите раздел «пустышка Запись в sys.modules») и future из функции.

+0

Хорошая ссылка ... Я на самом деле не заметил, что это документировано где-то раньше. Очевидно, почему-то я не искал очевидного титула «The Knights Who Say Neeeow ... Wum ... Ping». Ах, Python ... – bobince

+1

Я собирался опубликовать точный дубликат - мой второй сегодня: P –

ответ

23

None значения в sys.modules являются кэшированными отказами относительного поиска.

Так что, когда вы находитесь в пакете foo и вы import sys, Python выглядит первый для foo.sys модуля, и если это не идет в sys модуля верхнего уровня. Чтобы не было необходимости снова проверять файловую систему на foo/sys.py на дальнейший относительный импорт, она сохраняет None в sys.modules, чтобы указать, что модуль не существует, и последующий импорт не должен выглядеть там снова, но перейдите прямо к загруженному sys.

Это деталь реализации cPython, на которую нельзя положительно полагаться, но вам нужно будет знать ее, если вы делаете неприятный махический импорт/перезагрузку взлома.

Это происходит со всеми пакетами, а не только с logging. Например, import xml.dom и см. xml.dom.xml в списке модулей, когда он пытается импортировать xml изнутри xml.dom.

Поскольку Python движется к абсолютному импорту, это уродство будет меньше.

+0

Спасибо! Я добавил ссылки в моем вопросе на задний план и ссылаюсь на http://www.python.org/dev/peps/pep-0328 –

+0

Если это происходит со всеми пакетами, почему я никогда не видел это с помощью своих собственных материал? Я бы ожидал увидеть «mymodule.sys», «mymodule.os» и т. Д. С десятками и дюжинами таких фиктивных модулей, но вижу только некоторые из них, такие как xml.dom, logging и encodings (как D.Shawley упоминает). –

+0

Это происходит с моими пакетами. Но только пакеты, а не простые модули. – bobince

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 модуля.

Смежные вопросы