[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