bug? classes whose metclass has __del__ are not collectible
new-style classes keep track of their subclasses through weak-refs so they remain in general collectible. consider this code: (inspired by this post comp.lang.python post id: <b3khka$2g6$1@news.wplus.spb.ru> ) <test.py> import sys class MyMetaclass(type): def __init__(cls, name, bases, dict): super(MyMetaclass, cls).__init__(name, bases, dict) print 'initialized', cls.__name__ if 'meta__del__' in sys.argv: print "*meta__del__*" def __del__(cls): print 'deleted', cls.__name__ class MyClass(object): if 'meta' in sys.argv: print "*meta*" __metaclass__ = MyMetaclass pass class Sub(MyClass): pass del Sub import gc gc.collect() # force involved weak-refs to be cleared print "MyClass subclasses",MyClass.__subclasses__() print "garbage",gc.garbage </test.py> Now: C:\exp\py-subclasses-gc>\transit\Py23\python test.py MyClass subclasses [] garbage [] C:\exp\py-subclasses-gc>\transit\Py23\python test.py meta *meta* initialized MyClass initialized Sub MyClass subclasses [] garbage [] also Sub with both metaclass type or MyMetaclass without __del__ is collectible and collected but: C:\exp\py-subclasses-gc>\transit\Py23\python test.py meta meta__del__ *meta__del__* *meta* initialized MyClass initialized Sub MyClass subclasses [<class '__main__.Sub'>] garbage [<class '__main__.Sub'>] if MyMetaclass grows a __del__ method Sub is no longer collectible ...
new-style classes keep track of their subclasses through weak-refs so they remain in general collectible.
consider this code: (inspired by this post comp.lang.python post id: <b3khka$2g6$1@news.wplus.spb.ru>
I cannot find that article by id alone; groups.google.com doesn't have it.
<test.py> import sys
class MyMetaclass(type):
def __init__(cls, name, bases, dict): super(MyMetaclass, cls).__init__(name, bases, dict) print 'initialized', cls.__name__
if 'meta__del__' in sys.argv: print "*meta__del__*"
I'm guessing this should be indented the same as the following line.
def __del__(cls): print 'deleted', cls.__name__
class MyClass(object): if 'meta' in sys.argv: print "*meta*"
Ditto.
__metaclass__ = MyMetaclass pass
class Sub(MyClass): pass
del Sub
import gc
gc.collect() # force involved weak-refs to be cleared
print "MyClass subclasses",MyClass.__subclasses__() print "garbage",gc.garbage
</test.py>
Now:
C:\exp\py-subclasses-gc>\transit\Py23\python test.py MyClass subclasses [] garbage []
C:\exp\py-subclasses-gc>\transit\Py23\python test.py meta *meta* initialized MyClass initialized Sub MyClass subclasses [] garbage []
also Sub with both metaclass type or MyMetaclass without __del__ is collectible and collected but:
C:\exp\py-subclasses-gc>\transit\Py23\python test.py meta meta__del__ *meta__del__* *meta* initialized MyClass initialized Sub MyClass subclasses [<class '__main__.Sub'>] garbage [<class '__main__.Sub'>]
if MyMetaclass grows a __del__ method Sub is no longer collectible ...
In general objects whose class has a __del__ method are not collectible. The GC implementation has a good reason for this; someone else may be able to explain it. --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (2)
-
Guido van Rossum
-
Samuele Pedroni