Почему в sys.modules есть фиктивные модули? - PullRequest
17 голосов
/ 24 декабря 2009

Импорт стандартного модуля «logging» загрязняет 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) также имеют эту проблему. Почему?

Редактировать: Основываясь на ответе Бобинса, есть страницы, описывающие происхождение (см. Раздел "Фиктивные записи в sys.modules") и future из особенность.

Ответы [ 2 ]

23 голосов
/ 24 декабря 2009

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 голосов
/ 24 декабря 2009

Я не уверен, почему это происходит, но 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...