On Oct 7, 1:14 pm, Steven D'Aprano <st...@REMOVE-THIS-
cybersource.com.auwrote:
On Sun, 07 Oct 2007 16:38:23 +0000, Michele Simionato wrote:
On Oct 7, 12:26 pm, Marc 'BlackJack' Rintsch <bj_...@gmx.netwrote:
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