On Oct 7, 1:14 pm, Steven D'Aprano <[EMAIL PROTECTED] cybersource.com.au> wrote: > On Sun, 07 Oct 2007 16:38:23 +0000, Michele Simionato wrote: > > On Oct 7, 12:26 pm, Marc 'BlackJack' Rintsch <[EMAIL PROTECTED]> wrote: > > >> Drop all those `__del__()` methods as they prevent the garbage > >> collector from collecting "cycles". > > > I fully agree and I will add that __del__ methods are always a bad idea. > > Always? > > I recently wrote a bit of code where I needed to check that releasing the > first object in a tree-like structure would allow Python to garbage > collect all the other objects in a tree. I thought it would, but I wanted > to be sure ("don't guess, test"), so I wrote a simple class, gave it a > __del__ method that just printed self, inserted them in the tree, and > then deleted the first one. > > Worked like a charm. > > Without __del__, what should I have done to test that my code was > deleting objects and not leaking memory? > > What should I do when my objects need to perform some special processing > when they are freed, if I shouldn't use __del__?
The best thing is to use explicit resource management, for instance with a try .. finally or with the "with" statement in Python 2.5. The next best thing is to use weak references. I have some code for various experiments with wearefs I did some time ago, here it is: import itertools, weakref, sys, gc reference_list = [] # cannot be a set, you would lose references resource_counter = itertools.count(1) def resource(before_closing_callback=None, after_closing_callback=None): private = '_resource_%s' % resource_counter.next() def get(self): return getattr(self, private) def set(self, resource): setattr(self, private, resource) def close(ref): if before_closing_callback: before_closing_callback(resource) resource.close() if after_closing_callback: after_closing_callback(resource) reference_list.remove(ref) reference_list.append(weakref.ref(self, close)) return property(get, set) class FakeResource(object): def __init__(self, name): print 'opening resource %s' % name self.name = name def close(self): print 'closing resource %s' % self.name def __repr__(self): return '<FakeResource %r>' % self.name class Example(object): def __init__(self): self.resource1 = FakeResource('r1') self.resource2 = FakeResource('r2') def __del__(self): print '**************' self.resource1.close() self.resource2.close() def warn_before_closing(res): sys.stdout.write('going to close %s\n' % res) class Example2(object): resource1 = resource(warn_before_closing) resource2 = resource() def __init__(self): self.resource1 = FakeResource('r1') self.resource2 = FakeResource('r2') gc.set_debug(gc.DEBUG_LEAK) #e = Example() e = Example2() e.e = e del e print reference_list -- http://mail.python.org/mailman/listinfo/python-list