[Python-Dev] reference leaks, __del__, and annotations

Tim Peters tim.peters at gmail.com
Wed Apr 5 04:32:48 CEST 2006


[Tim Peters]
>> A problem is that the variant semantics also seem pretty arbitrary ;-),
>> and there's a dearth of compelling use cases to guide a decision.

[Greg Ewing]
|> At the time I think I suggested that it would be
> reasonable if weakref callbacks were guaranteed to
> be called as long as they weren't trash themselves
> and they didn't reference any trash. From what you
> said in a recent message, it sounds like that's
> the way it currently works.

Nope, and that was the point of the first message in the thread I
referenced.  The issues were explained well in that thread, so I don't
want to repeat it all here again.

> These semantics would be sufficient to be able to
> use weakrefs to register finalisers, I think. You
> keep a global list of weakrefs with callbacks that
> call the finalizer and then remove the weakref
> from the global list.
>
> I'll put together a prototype some time and see if
> it works. I actually have a use case at the moment --
> a couple of types that need to release external
> resources, and since they're part of a library
> I'm distributing, I can't be sure people won't put
> them in cycles.

Note that it's very easy to do this with __del__.  The trick is for
your type not to have a __del__ method itself, but to point to a
simple "cleanup object" with a __del__ method.  Give that "contained"
object references to the resources you want to close, and you're done.
 Because your "real" objects don't have __del__ methods, cycles
involving them can't inhibit gc.  The cleanup object's only purpose in
life is to close resources.  Like:

class _RealTypeResourceCleaner:
    def __init__(self, *resources):
        self.resources = resources

    def __del__(self):
        if self.resources is not None:
            for r in self.resources:
                r.close()
            self.resources = None

    # and typically no other methods are needed, or desirable, in
    # this helper class

class RealType:
    def __init__(*args):
        ...
        # and then, e.g.,
        self.cleaner = _ResourceCleaner(resource1, resource2)

    ... tons of stuff, but no __del__ ....

That's the simple, general way to mix cycles and __del__ without problems.


More information about the Python-Dev mailing list