Semi-automatic resource management with AutoClose --------------------------------------------------- I have read in my life code where the release of a resource was done in the destructor method, relying on Python reference counting garbage collector. This kind of code is very fragile, since Python does not make any guarantee at all about *when* the destructor will be called. Consider for instance this code (coming from a real life case):
$ cat deallocating.py import logging class C(object): def __init__(self): logging.warn('Allocating resource ...') def __del__(self): logging.warn('De-allocating resource ...') print 'THIS IS NEVER REACHED!' if __name__ == '__main__': c = C() $ python deallocating.py WARNING:root:Allocating resource ... Exception exceptions.AttributeError: "'NoneType' object has no attribute 'warn'" inThe issue here is that the destructor is called *too late*, when the cleanup mechanism (see http://www.python.org/doc/essays/cleanup) has already set logging to None. This recipe 1) gets rid of the destructor, and put the responsibility of deallocating the resource in a .close method (which is IMO opinion much clearer); 2) used in conjunction with the contextlib.closing class (new in Python 2.5) it allows to perform explicit resource deallocation with the 'with' statement, which is the preferred way to do that in Python 2.5; 3) at the end of the program, it automatically closes the resources which were not closed explicitely before. The usage is pretty simple. You should just import from the autoclose module the AutoClose class and you should add it to the list of your base classes. Then you should override the .close method making sure it calls the base class .close. Here is an example:> ignored
$ cat autoclose_ex.py import logging from autoclose import AutoClose class C(AutoClose): def __init__(self, id): self.id = id def close(self): logging.warn('closing object %s' % self.id) super(C, self).close() class D(C): pass c1 = C(1) c2 = C(2) d3 = D(3) $ python autoclose_ex.py Closing instances ofNotice that AutoClose keeps in memory a potentially large lists of instances, therefore your are advised to explicitly close your objects as soon as possible, to keep the list short. You can remove all the instances of a given class (and its subclasses) with the (meta)methodClosing instances of WARNING:root:closing object 1 WARNING:root:closing object 2 Closing instances of WARNING:root:closing object 3