It is __del__ calling twice for some instances?
Hello! It is correct behaviour for python to call __del__ on some identity of a class object more than once? In brief I shall describe a situation. Sorry for my english. For debugin purposes I'm put in my module global counters for counting __init__ and __del__ calls. This is a sample code for clearness: --- init_cnt = 0 del_cnt = 0 class foo: def __init__(self): global init_cnt init_cnt += 1 def __del__(self): global del_cnt del_cnt += 1 def stat(): print "init_cnt = %d" % init_cnt print "del_cnt = %d" % del_cnt print "difference = %d" % init_cnt-del_cnt --- And the result of a stat() call in some moment of time looks like so: init_cnt = 6233 del_cnt = 6234 difference = -1 It is __del__ called twice for some instance? Thanks in advance! -- GMT More Then ... -- http://mail.python.org/mailman/listinfo/python-list
Re: It is __del__ calling twice for some instances?
Max Yuzhakov writes: MY> print "difference = %d" % init_cnt-del_cnt Little correction. print "difference = %d" % (init_cnt-del_cnt) -- GMT More Then ... -- http://mail.python.org/mailman/listinfo/python-list
Re: It is __del__ calling twice for some instances?
Duncan Booth пишет: DB> Not with the code which you gave as an example, but in the general case DB> yes, the only guarantee that Python gives about the __del__ method on an DB> instance is that it will be called zero, one or more than one times during DB> the run of the program. In practice there are various situations where DB> __del__ will not be called, but it is only called multiple times if you DB> resurrect the object during a call to __del__. No, only presented code in __del__ do increment of global variable del_cnt. DB> The output from your stat function could, of course, also be generated by DB> creating and destroying lots of foo objects in another thread. If a foo was DB> both created and destroyed between the first two print statements, and DB> another one was created and destroyed in the middle of the evaluation of DB> the last print statement then you could see the output you described DB> without any multiple __del__ calls in the same object. No, it's a single-threaded code. DB> You should post a working code sample which generates your output if you DB> want a more useful answer. I'm sorry for mess with a code. I have forgotten to write, that is only fragments for demonstration of essence of a question. Real code in this module has 880 lines and I shall not abuse your time. I shall try to solve a problem by debuger. And thank for Your answer! -- GMT More Then ... -- http://mail.python.org/mailman/listinfo/python-list
Re: It is __del__ calling twice for some instances?
Duncan Booth wrote: DB> You should post a working code sample which generates your output if you DB> want a more useful answer. Hello! Today I have found a compact variant of a code which shows my question: --- #!/usr/local/bin/python -d # -*- coding: koi8-u -*- class foo: def __init__(self, other): self.other = other global ini_cnt ini_cnt +=1 def __del__(self): global del_cnt del_cnt +=1 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 = 75 a = foo(None) for i in xrange(loop_cnt): a = foo(a) stat() a = None stat() --- And result is: ini_cnt = 76 del_cnt = 0 difference = 76 ini_cnt = 76 del_cnt = 77 difference = -1 Why for some instance __del__ called twice? Such behaviour of __del__ seems to me unpredictable. Thanks for Your attention! -- GMT More Then ... -- http://mail.python.org/mailman/listinfo/python-list
Re: It is __del__ calling twice for some instances?
Duncan Booth wrote: DB> I figured out what is going on in the code to deallocate an old-style class DB> instance: DB> DB> The reference count is temporarily incremented. DB> DB> If the class has a __del__ method then a descriptor is created for the DB> method and called. When the call returns, the descriptor is released. DB> DB> Then the object itself is released using special code to avoid a recursive DB> call to the deallocator. DB> DB> However, if the trashcan mechanism is invoked by the attempt to release the DB> descriptor, it actually queues the descriptor in the trashcan. Since the DB> descriptor contains a reference to the object it has effectively DB> resurrected it. This means the special code to avoid the recursive call DB> simply decrements the reference count but does not release anything (the DB> object has been resurrected by the descriptor). When the descriptor is DB> later released the __del__ method is triggered a second time. Thank You for so detailed explanation! -- GMT More Then ... -- http://mail.python.org/mailman/listinfo/python-list
Re: It is __del__ calling twice for some instances?
Duncan Booth wrote: DB> BTW, the behaviour is completely different if you use a new style class, DB> but still somewhat bizarre: for new style classes only the first 25 objects DB> get freed when you clear a, the remainder are only released by the garbage DB> collector. If to add the third call of stat() after the second, the result became such: ini_cnt = 51 del_cnt = 0 difference = 51 ini_cnt = 51 del_cnt = 25 difference = 499976 ini_cnt = 51 del_cnt = 51 difference = 0 Preceding call to gc.disable() has no influence on result. -- GMT More Then ... -- http://mail.python.org/mailman/listinfo/python-list