I am curious about the details of __del__ in python, when and why it should be used and what it shouldn't be used for.  I've learned the hard way that it is not really like what one would naively expected from a destructor, in that it is not the opposite of __new__ / __init__.  
class Foo(object):
    def __init__(self):
        self.bar = None
    def open(self):
        if self.bar != 'open':
            print 'opening the bar'
            self.bar = 'open'
    def close(self):
        if self.bar != 'closed':
            print 'closing the bar'
            self.bar = 'close'
    def __del__(self):
        self.close()
if __name__ == '__main__':
    foo = Foo()
    foo.open()
    del foo
    import gc
    gc.collect()
I saw in the documentation that it is not guaranteed __del__() methods are called for objects that still exist when the interpreter exits.  
- how can it be guaranteed that for any Fooinstances existing when the interpreter exits, the bar is closed?
- in the code snippet above does the bar get closed on del fooor ongc.collect()... or neither? if you want finer control of those details (e.g. the bar should be closed when the object is unreferenced) what is the usual way to implement that?
- when __del__is called is it guaranteed that__init__has already been called? what about if the__init__raised?
 
     
     
     
    