tags:

views:

129

answers:

2

Importing the standard "logging" module pollutes sys.modules with a bunch of dummy entries:

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

So importing this package puts extra names into sys.modules, except that they are not modules, just references to None. Other modules (e.g. xml.dom and encodings) have this issue as well. Why?

Edit:* Building on bobince's answer, there are pages describing the origin (see section "Dummy Entries in sys.modules") and future of the feature.

+8  A: 

None values in sys.modules are cached failures of relative lookups.

So when you're in package foo and you import sys, Python looks first for a foo.sys module, and if that fails goes to the top-level sys module. To avoid having to check the filesystem for foo/sys.py again on further relative imports, it stores None in the sys.modules to flag that the module didn't exist and a subsequent import shouldn't look there again, but go straight to the loaded sys.

This is a cPython implementation detail you can't usefully rely on, but you will need to know it if you're doing nasty magic import/reload hacking.

It happens to all packages, not just logging. For example, import xml.dom and see xml.dom.xml in the module list as it tries to import xml from inside xml.dom.

As Python moves towards absolute import this ugliness will happen less.

bobince
Thanks! I added links in my question to background in, and referenced by, http://www.python.org/dev/peps/pep-0328
Peter Hansen
If it "happens to all packages", why have I never seen this with my own stuff? I'd expect to see "mymodule.sys", "mymodule.os" and so forth with dozens and dozens of such dummy modules around but only see it with a few like xml.dom, logging, and encodings (as D.Shawley mentions).
Peter Hansen
It happens to my packages. But only packages, not simple modules.
bobince
Strange. I'm dead certain I've frequently checked sys.modules in the past for various debugging purposes, without noticing dozens of stdlib modules referenced in sys.modules as dummy modules under my subpackages. Yet there they are, with things like 'xxx.xxx.sys' showing up 16 times, for example.
Peter Hansen
A: 

I'm not sure why it happens but encodings exhibits the same references to 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'>

I don't really know what is going on with some of the entries being None but I can say that it is not unique to the logging module.

D.Shawley