2006-11-05
An interesting Python garbage collection bug
Derived from here:
import sys x = 10 del sys.modules['__main__'] print x
If you execute this at the interpreter prompt, you get a NameError
that x
is not defined. If you execute it as a file (or if you put
the sys.modules and print bit in a function and run the function),
you get None
printed.
The interpreter situation makes a certain amount of sense, once you
discover that the interpreter is holding no references to anything
from prompt to prompt. The del
drops the reference count on the real
__main__ to zero, causing it to be garbage collected, and you are left
with no namespace at all.
(Technically what happens is that the interpreter recreates a new __main__ at the next line, but it is empty. You can't do much with this, since you can't successfully import __builtins__ to start reconstructing an environment.)
The function case makes sense once you think about cyclic garbage
collection. While the executing function has a reference to __main__,
__main__ also holds a reference to it, making it a cyclic reference and
thus not enough to keep __main__ alive.
The peculiar result is because of how CPython cleans up modules that are
getting garbage collected; in order to help out destructors, it follows
a complicated dance of setting module-level names to None
(in two
passes, and excluding __builtins__, so that destructors can still get at
builtin objects), instead of actually deleting them outright.
I call this a bug because I believe that executing code should be considered to be holding an external reference to its module, and that the interpreter should similarly hold an external reference to __main__ in general. Python may be doing what you told it to here, but it's not anywhere near what I think most people would expect.