Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get all instances of a certain class in python?

Tags:

python

class

Someone asked a similar one [question]:Printing all instances of a class. While I am less concerned about printing them, I'd rather to know how many instances are currently "live". The reason for this instance capture is more like a setting up a scheduled job, every hour check these "live" unprocessed instances and enrich the data. After that, either a flag in this instance is set or just delete this instance. Torsten Marek 's answer in [question]:Printing all instances of a class using weakrefs need a call to the base class constructor for every class of this type, is it possible to automate this? Or we can get all instances with some other methods?

like image 443
NathaneilCapital Avatar asked Sep 12 '25 22:09

NathaneilCapital


2 Answers

You can either track it on your own (see the other answers) or ask the garbage collector:

import gc

class Foo(object):
   pass

foo1, foo2 = Foo(), Foo()

foocount = sum(1 for o in gc.get_referrers(Foo) if o.__class__ is Foo)

This can be kinda slow if you have a lot of objects, but it's generally not too bad, and it has the advantage of being something you can easily use with someone else's code.

Note: Used o.__class__ rather than type(o) so it works with old-style classes.

like image 84
kindall Avatar answered Sep 15 '25 11:09

kindall


If you only want this to work for CPython, and your definition of "live" can be a little lax, there's another way to do this that may be useful for debugging/introspection purposes:

>>> import gc
>>> class Foo(object): pass
>>> spam, eggs = Foo(), Foo()
>>> foos = [obj for obj in gc.get_objects() if isinstance(obj, Foo)]
>>> foos
[<__main__.Foo at 0x1153f0190>, <__main__.Foo at 0x1153f0210>]
>>> del spam
>>> foos = [obj for obj in gc.get_objects() if isinstance(obj, Foo)]
>>> foos
[<__main__.Foo at 0x1153f0190>, <__main__.Foo at 0x1153f0210>]
>>> del foos
>>> foos = [obj for obj in gc.get_objects() if isinstance(obj, Foo)]
>>> foos
[<__main__.Foo at 0x1153f0190>]

Note that deleting spam didn't actually make it non-live, because we've still got a reference to the same object in foos. And reassigning foos didn't not help, because apparently the call to get_objects happened before the old version is released. But eventually it went away once we stopped referring to it.

And the only way around this problem is to use weakrefs.

Of course this will be horribly slow in a large system, with or without weakrefs.

like image 31
abarnert Avatar answered Sep 15 '25 11:09

abarnert