Roger Dahl Roger Dahl - 1 month ago 4
Python Question

In Python, how do I determine if an object still exists?

How do I determine if an object that has been created earlier in my Python program still exists? By exists, I mean, is still reachable through some other object for which I still hold a reference.

Background:

I'm trying to use a parser which may be buggy. The parser returns an object with members that have recursive references. The object can't be pickled or dumped with any of the debug dump commands I've found online. When I step through the parser, I can see an object that I will need to access later get created. But it looks to me as if the object does not end up actually getting referenced in the object that is returned from the parser. I would like to determine if the object that I saw getting created in the debugger is available somewhere in the object that the parser returned.

Answer

The gc module is the way to debug this kind of information. For example:

import gc

a = [1, 2, 3]
b = [a, a]
gc.collect()
refs = gc.get_referrers(a)

We know the a variable itself refers to the object. Or, more accurately, the globals of the __main__ module have refer to that object, under the value associated with the key a. But are there any other refs?

print(len(refs))
print(refs)

This prints 2. And then, in addition to printing the module's globals, it also prints out [[1, 2, 3], [1, 2, 3]], the value of b.

So, if you know how many references to the object will exist beside the one you're looking for (much trickier in real life than in a trivial example), or you have some way of identifying the value that you're trying to check, gc.get_referrers can do what you want. If you don't know either of those, there's really know way to figure it out short of by picking through the whole referrers list and trying to figure it out, which gets very hard.


An alternative way to do this, of course, is to provide a function that walks your data structures and searches for the value you were looking for. This can be difficult or even impossible for some structures, but if you can do it, it's often worth doing for all kinds of debugging reasons, not just this one.


Or, of course, if you can add a __del__ method to your object, you can prove that it no longer exists (by logging a call to its __del__), but that doesn't help prove that it does exist (it may have no live referents, but not have been collected yet… in fact, just adding a __del__ may prevent it from being collected, if it's in a cycle).

Comments