Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is __subclasses__() cached?

I have three models in three different files. The modules are all in sys.path

a.py:
class A(object):
    pass

b.py:
class B(A):
    passs

c.py:
class C(A):
    pass

Now I want to get the subclasses of A:

print A.__subclasses__()
>> [<class 'b.B'>, <class 'c.C'>]

So far so good. But now I remove c.py from my sys.path and get the subclasses again. I would except, that there will be only B left. But the output is the same:

# remove c.py from sys.pyth
sys.path.remove('../c')
print A.__subclasses__()
>> [<class 'b.B'>, <class 'c.C'>]

So somehow the __subclasses__ call is cached. Is it possible to force __subclasses__ to search sys.path again?

like image 335
ilse2005 Avatar asked Jul 31 '26 13:07

ilse2005


1 Answers

No, class.__subclasses__() is not cached, not really; the internal implementation uses weak references. But modules are; removing the c.py file will not unload the module.

You'd have to delete the module too:

import sys

del sys.modules['c']

and make sure to have no other references to the module.

Because classes involve a lot of references themselves (they point to their base classes, for starters) you need to make sure you run gc.collect() to make sure the deleted class objects are no longer retained in memory:

>>> class B(A): pass
... 
>>> A.__subclasses__()
[<class '__main__.B'>]
>>> del B
>>> A.__subclasses__()
[<class '__main__.B'>]
>>> gc.collect(0)
0
>>> gc.collect(1)
3
>>> gc.collect(1)
0
>>> gc.collect(2)
0
>>> A.__subclasses__()
[]
like image 50
Martijn Pieters Avatar answered Aug 02 '26 04:08

Martijn Pieters