views:

228

answers:

5

Should it be possible for gc.get_referrers(obj) to return an empty list for an object, but the object still be accessible through a weak reference?

If so how would I start trying to identify the cause for this object not being garbage collected?

Edit: I'm not sure exactly how a code sample would help in this case - there's obviously a strong reference somewhere, but I'll be damned if I can find it. I was of the impression that all strong references to an object would be identified by get_referrers().

Edit: Solved. I found the variable with a strong reference - It was inside the game event loop but wasn't a class variable so get_referrers wasn't picking it up.

+1  A: 

Yes: http://docs.python.org/library/weakref.html

A weak reference won't be keeping the object alive.

The get_referrers() function will only locate those containers which support garbage collection; extension types which do refer to other objects but do not support garbage collection will not be found.

What makes you think the object isn't getting collected? Also, have you tried gc.collect()?

Christopher
I still get an object instance through my weakref, when I'd expect a None.
gridzbi
Are you certain there is not a strong reference elsewhere? Also garbage collection is not automatic (even with ref counting, if there is a cycle of references those will wait until a different garbage collection algorithm is used)
Kathy Van Stone
Yes, but for how long? Forever? ie, you leave the program running for a long, long time, and the object never collects? Python's GC is generational, so it may take some time for the object to get collected.
Christopher
A: 

As Christopher says, a weak reference does not count into object refcount, and therefore is not able to keep Python from deleting an object.

However, Python's garbage collector does not delete objects that are in a circular reference and have a __del__ method defined.
You can check (and fix) such situation by using gc.garbage.

Roberto Liffredo
gc.garbage is an empty list after calling gc.collect() - neither the object nor its superclasses define __del__. Would circular references be identifiable by the list returned by gc.get_referrers()?
gridzbi
A: 

If you do have a strong reference to the object, use gc.get_referrers(obj) to find it.

This can help if you have a leak and don't know what's leaking:

http://mg.pov.lt/objgraph.py http://mg.pov.lt/blog/hunting-python-memleaks http://mg.pov.lt/blog/python-object-graphs.html

It's a thin wrapper around the inspect module; it can help a lot if you have hard-to-track unwanted references. For just tracking down a reference, though, gc.get_referrers is probably all you need.

Glenn Maynard
+1  A: 

It might also be the case that a reference was leaked by a buggy C extension, IMHO you will not see the referer, yet still the refcount does not go down to 0. You might want to check the return value of sys.getrefcount.

Torsten Marek