[Python-ideas] breaking cycles that include __del__

Scott Dial scott+python-ideas at scottdial.com
Mon Oct 19 22:46:43 CEST 2009


Daniel Stutzbach wrote:
> Unfortunately, if the object ends up in a cycle, then the recipe can't
> do its job because __del__ will never be called.

The way I have always dealt with these problems is to not have
overly-generalized objects. If I have a resource to acquire that needs
to have a __del__ to clean-up after itself (as you suggest, in case a
close() was not called), then that is *all* that object does. The only
way you can get trapped into a cycle is if you design a
resource-managing object that holds references to other objects, which
was bad design.

I don't see the need for a recipe like the one Nick linked to. Everyone
can agree it is ugly, I think. But, the real goal was to split out the
core of the object required for clean-up. So, I am saying, actually
split it out! Classes are cheap.

class _CoreWidget:
    def __init__(self, *args, **kwds):
        self.closed = False
        # Acquire resources

    def close(self):
        if self.closed:
            return
        self.closed = True
        # Free resources

    def __del__(self):
        if not self.closed:
            print('%s not closed properly' % repr(self))
            self.close()

class Widget:
    def __init__(self, *args, **kwds):
        self._core_widget = _CoreWidget(*args, **kwds)

x, y = Widget(), Widget()
x.y, y.x = y, x
del x; del y
# <__main__._CoreWidget instance at 0x00B3F418> not closed properly
# <__main__._CoreWidget instance at 0x00B3E328> not closed properly

-- 
Scott Dial
scott at scottdial.com
scodial at cs.indiana.edu




More information about the Python-ideas mailing list