Weakref.ref callbacks and eliminating __del__ methods

Mike C. Fletcher mcfletch at rogers.com
Mon Jan 24 16:14:40 CET 2005

Richie Hindle wrote:

>>I'll note that one fairly obvious pattern works very well for weakrefs
>>and __del__ methods (mutatis mutandis):  don't put the __del__ method
>>in self, put it in a dead-simple object hanging *off* of self.  Like
>>the simple:
>>class BTreeCloser:
>>    def __init__(self, btree):
>>        self.btree = btree
>>    def __del__(self):
>>        if self.btree:
>>            self.btree.close()
>>            self.btree = None
>>Then give self an attribute refererring to a BTreeCloser instance, and
>>keep self's class free of a __del__ method.  The operational
>>definition of "dead simple" is "may or may not be reachable only from
>>cycles, but is never itself part of a cycle".
>This is very nice - I've been wondering about just this problem recently,
>and this will be very useful.  Many thanks!
 From me too :)

>One question: why the `self.btree = None` in the last line?  Isn't
>`self.btree` guaranteed to go away at this point anyway?  (If the answer
>is "it's necessary for weird cases that would take an hour to explain"
>then I'll be more than happy to simply use it.  8-)
It's to allow the Closer object to act as a substitute for a .close() 
method on the object, the final full code of the Closer looks like this:

class Closer( object ):
    """Close the OIDStore"""
    def __init__( self, client ):
        """Initialise the closer object"""
        self.btree = client.btree
    def __call__( self ):
        """Close and cleanup to prevent multiple calls"""
        if self.btree:
            self.btree = None
    def __del__( self ):
        """Handle deletion of the closer object (close btree if 

and we store one of these as self.close in the OIDStore instance' 

        self.close = Closer( self )

If the user explicitly calls storage.close() we don't want the __del__ 
trying to re-close the storage later.  In other words, its an explicit 
requirement for *this* __del__, not a general requirement.

Have fun,

  Mike C. Fletcher
  Designer, VR Plumber, Coder

More information about the Python-list mailing list