It is __del__ calling twice for some instances?

Duncan Booth duncan.booth at invalid.invalid
Fri Aug 18 03:50:56 EDT 2006


Max Yuzhakov wrote:

> Why for some instance __del__ called twice?
> Such behaviour of __del__ seems to me unpredictable.

Here's a slightly modified version of your code. The 51st object destroyed 
gets its __del__ method called twice. It doesn't matter how long your loop 
is, every 50th object gets special treatment (or perhaps it is the 49th).

The good news is that there is a way to stop it happening: just add an 
explicit "del self.other" at the end of __del__. The bad news is that if 
your list is too long that will cause a flood of error messages and won't 
call the destructors at all past the first 1000.

As to why it happens, there is a mechanism in Python to stop unlimited 
stack being used when objects are freed: when the stack gets too deep then 
instead of being released, the Py_DECREF call puts the object into a 
trashcan list and the objects aren't released until the stack has unwound.
It looks like there must be a bug round the trashcan mechanism somewhere. 

BTW, the behaviour is completely different if you use a new style class, 
but still somewhat bizarre: for new style classes only the first 25 objects 
get freed when you clear a, the remainder are only released by the garbage 
collector.

#!/usr/local/bin/python -d
# -*- coding: koi8-u -*-

class foo:
    def __init__(self, other):
        self.other = other
        self._deleted = False

        global ini_cnt
        ini_cnt +=1

    def __del__(self):
        if self._deleted:
            print "aargh!"
        self._deleted = True
        global del_cnt
        del_cnt +=1
        print "del",del_cnt,"at",id(self)

def stat():
    print "-"*20
    print "ini_cnt = %d" % ini_cnt
    print "del_cnt = %d" % del_cnt
    print "difference = %d" % (ini_cnt-del_cnt)

ini_cnt = 0
del_cnt = 0
loop_cnt = 54

a = foo(None)

for i in xrange(loop_cnt):
    a = foo(a)

stat()
a = None
stat()




More information about the Python-list mailing list