Python: find all instances of a class with gc.get_objects()

Xanthian class.

Here’s a lovely hack that I’ve used when machete-mode debugging.

Say you have a class, and you want to find its live instances, perhaps to check how many there are or what value a certain attribute has across them. Normally you'd have to alter the class initialization to store its instances in a collection, like a WeakSet, but making such edits slows down debugging and isn’t always possible. The approach in this post uses the garbage collector module, gc, to leverage its already-tracked references to the class in question, no restart required.

The function gc.get_objects() traverses (nearly) all live objects tracked by the garbage collector and returns a list of them. (It misses some kinds of special objects that are not tracked by the garbage collector, but that’s very rarely a concern.) We can use it with a list comprehension to filter for instances of a given class:

import gc

instances = [obj for obj in gc.get_objects() if isinstance(obj, MyClass)]

This approach can be slow, because it traverses all live objects, puts them in a list, and then filters them with an isinstance() on each one. However, that’s normally fine for debugging purposes.

Another concern is that while instances exists, its references will keep the objects alive. To avoid this problem, you can del the list when you’re done with it:

instances = [obj for obj in gc.get_objects() if isinstance(obj, MyClass)]
for instance in instances:
    if instance.status == "error":
        print(f"Found an error instance: {instance}")
del instances  # allow the instances to be garbage collected

Alternatively, you can pass over the instances with a generator expression, to avoid creating instances at all. For example, to gather statistics on a status attribute across all instances, you could use a Counter with a generator expression:

import gc
from collections import Counter

status_counter = Counter(
    obj.status for obj in gc.get_objects() if isinstance(obj, MyClass)
)
print(f"Status counts: {status_counter}")

Fin

Go go gadget garbage collector!

—Adam


😸😸😸 Check out my new book on using GitHub effectively, Boost Your GitHub DX! 😸😸😸


Subscribe via RSS, Twitter, Mastodon, or email:

One summary email a week, no spam, I pinky promise.

Related posts:

Tags: