__del__ not called?

Tim Peters tim.peters at gmail.com
Mon Mar 13 04:00:42 EST 2006


[Duncan Booth]
> No, Python doesn't run the garbage collector when it is exiting.

Actually, it does.  What it doesn't do is call the garbage collector
twice when it exits, although it used to ;-)

> What it does is to delete all the globals from each module in turn. So:

Yup.  The code is in function Py_Finalize().  Here's the relevant snippet:

	...
	PyGC_Collect();

	/* Destroy all modules */
	PyImport_Cleanup();

	/* Collect final garbage.  This disposes of cycles created by
	 * new-style class definitions, for example.
	 * XXX This is disabled because it caused too many problems.  If
	 * XXX a __del__ or weakref callback triggers here, Python code has
	 * XXX a hard time running, because even the sys module has been
	 * XXX cleared out (sys.stdout is gone, sys.excepthook is gone, etc).
	 * XXX One symptom is a sequence of information-free messages
	 * XXX coming from threads (if a __del__ or callback is invoked,
	 * XXX other threads can execute too, and any exception they encounter
	 * XXX triggers a comedy of errors as subsystem after subsystem
	 * XXX fails to find what it *expects* to find in sys to help report
	 * XXX the exception and consequent unexpected failures).  I've also
	 * XXX seen segfaults then, after adding print statements to the
	 * XXX Python code getting called.
	 */
#if 0
	PyGC_Collect();
#endif

The first PyGC_Collect() runs, then what you described runs ("destroy
all modules"), and then  PyGC_Collect() _doesn't_ run again.  As the
comment says, it's the second run of PyGC_Collect() that _would_ get
rid of dead module-level new-style classes, were it to run.

Alas, as the XXX comments say, too much of the interpreter has been
destroyed by PyImport_Cleanup() for __del__ and weakref callbacks to
execute sanely, so we have to skip it.  And, of course, module-level
objects _aren't_ trash before PyImport_Cleanup() runs.  Therefore
module-level objects involved in reference cycles never trigger
__del__ or weakref callbacks as a side effect of Python exiting, and
new-style classes are (as you said) always involved in reference
cycles.



More information about the Python-list mailing list