<div class="gmail_quote">On Sat, Oct 17, 2009 at 9:34 AM, Daniel Stutzbach <span dir="ltr"><<a href="mailto:daniel@stutzbachenterprises.com">daniel@stutzbachenterprises.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
I propose the following simple solution.  When the garbage collector is about to add an object to gc.garbage, it checks to see if the object has a __clear__ method.  If so, the garbage collector calls it, giving the object an opportunity to safely break any cycles it may be in.  If it breaks the cycles, great!  The object can now safely be collected and __del__ will eventually be called.  If not, then the object gets added to gc.garbage after all and no harm is done.<br>
</blockquote></div><br>I should add that my personal use-case runs something like this.<br><br>Obviously, most uses of __del__ revolve around object with with special resources that need to be freed "by hand" (such as a resource allocated via ctypes).  To guarantee the timely freeing of resources, it's always better to close the object by hand with a .close() method or using a context manager.  That works great, except there's often no easy way to test a program to verifying that .close is always called when appropriate.  <br>
<br>There's a simple recipe to make sure that .close() was called on an object, by using __del__ to make sure the object was closed "by hand":<br><br>class Widget:<br>  closed = False<br><br>  def close(self):<br>
    if self.closed: return<br>    self.closed = True<br>    # Free various resources from ctypes, etc.<br><br>  def __del__(self):<br>    log_an_error('%s not closed properly' % repr(self))<br>    self.close()<br>
<br>Unfortunately, if the object ends up in a cycle, then the recipe can't do its job because __del__ will never be called.<br><br>I think I'll experiment by having my program periodically check gc.garbage and call any __clear__ methods it finds.  For that matter, I may just call any __del__ methods it finds and see what happens.  If the order of calls to __del__ matters, I'll try it as a bug in my __del__ methods.<br>
<blockquote style="margin: 1.5em 0pt;">--<br>
Daniel Stutzbach, Ph.D.<br>
President, <a href="http://stutzbachenterprises.com">Stutzbach Enterprises, LLC</a>
</blockquote>