<br>Thanks Giovanni, <br><br> That's very helpful.<br><br>Charles.<br><br><b><i>Giovanni Bajo <rasky@develer.com></i></b> wrote:<blockquote class="replbq" style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px;"> On mar, 2007-07-31 at 13:11 -0700, charles chen wrote:<br><br>> <br>> Thanks Phil for your help with our memory lapse.<br>> <br>> We've come across another issue: the Python garbage collector<br>> isn't sussing out circular references properly.<br>> <br>> A previous post by you say that this should be working:<br>> <br>> http://www.riverbankcomputing.com/pipermail/pyqt/2007-May/016237.html<br>> <br>> Here's a simple demonstration:<br>> <br>> >>> from PyQt4.QtCore import QObject<br>> >>> class q(QObject):<br>> ... def init(self):<br>> ... QObject.init(self)<br>> ... def __del__(self):<br>> ... print 'q deleted.'<br>>
...<br>> >>> q1 = q()<br>> >>> q1 = None<br>> q deleted.<br>> >>> q2 = q(<br>> >>> q2.circularReference = q2<br>> >>> q2 = None<br>> >>> q3 = q()<br>> >>> q3.circularReference = q3<br>> >>> q3.deleteLater()<br>> >>> q3 = None<br>> >>> import gc<br>> >>> gc.collect()<br>> 0<br>> >>> q4 = q()<br>> >>> q4.circularReference = q4<br>> >>> q4.circularReference = None<br>> >>> q4 = None<br>> q deleted.<br>> <br>> q2 and q3 are never gc'ed.<br>> <br>> We're also seeing this in production. Are we doing something<br>> wrong? <br><br>Yes the garbage collector doesn't work with objects containing __del__.<br>That's true since GC was introduced in Python 2.0. If you activate GC<br>debug mode (via gc.set_flags() or whatever it is called), run an<br>explicit gc.collect() call,
and look at gc.garbage, you should find your<br>q2 and q3 there, as they are classified as "uncollectable" <br><br>Try rewriting your example without __del__ and it will work. To issue a<br>pring when an object is collected without using __del__, you have 2<br>alternatives:<br><br>a) Use Python's weakref, which allows to register a callback function<br>invoked when an object is about to be collected.<br>b) Use Qt's SIGNAL("destroyed()"), emitted by all QObjects when they are<br>in the process of being destroyed.<br><br>Either way, you will see that your objects are collected. <br><br>Notice that using a weakref internally within a class is a good way to<br>replace existing code using __del__ and make it GC-friendly.<br>-- <br>Giovanni Bajo<br><br><br></blockquote><br>