Circular references not being cleaned up by Py_Finalize()

Hrvoje Niksic hniksic at
Wed Mar 26 10:02:09 CET 2008

blackpawn <pharmapsychotic at> writes:

> I know the garbage collector is tracking the object because it
> properly calls the traverse function but for whatever reason it
> never calls the clear function.  Does anyone have experience with
> circular references and had success with it or the example in the
> docs?

I've now tried it, and it seems to work.  Modifying Nody_dealloc with
printf("collecting %p\n", self), it works like this:

>>> import noddy4
>>> n = noddy4.Noddy()
>>> n.first = n
>>> del n         # n would be dealloced here without the cycle
>>> ^D
collecting 0xb7d3bf2c

So the garbage-collector is invoked at least once before shutdown.
However, it doesn't work without "del n" line, so it would appear that
the gc is not invoked after the module cleanup and therefore doesn't
explicitly dealloc global objects that contain cycles.  You can work
around that by using the atexit module to register a cleanup function
that removes your global objects from the module namespace(s) and, if
necessary, invokes gc.collect() manually.  That way your objects end
up as reclaimable garbage.

This won't work if your cycle-containing objects are indirectly
reachable from the module namespace through other containers not under
your control.  In that case, you should really rethink your strategy
of depending on finalizers to run and perhaps use atexit to do your
exit processing or, as others pointed out, use scope tools
(try/finally, with) at the entry point of your code.

More information about the Python-list mailing list