Python file with closing automatically
03 December 2011
Perhaps someone who knows more about the internals of python and the recent changes in 2.6 and 2.7 can explain this question that came up today in a code review.
I suggest using
with instead of
try: ... finally: to close a file that was written to. Instead of this:
dest = file('foo', 'w') try: dest.write('stuff') finally: dest.close() print open('foo').read() # will print 'stuff'
We can use this:
with file('foo', 'w') as dest: dest.write('stuff') print open('foo').read() # will print 'stuff'
Why does that work? I'm guessing it's because the
file() instance object has a built in
__exit__ method. Is that right?
That means I don't need to use contextlib.closing(thing) right?
For example, suppose you have this class:
class Farm(object): def __enter__(self): print "Entering" return self def __exit__(self, err_type, err_val, err_tb): print "Exiting", err_type self.close() def close(self): print "Closing" with Farm() as farm: pass # this will print: # Entering # Exiting None # Closing
Another way to achieve the same specific result would be to use the
class Farm(object): def close(self): print "Closing" from contextlib import closing with closing(Farm()) as farm: pass # this will print: # Closing
closing() decorator "steals" the
__exit__. This last one can be handy if you do this:
from contextlib import closing with closing(Farm()) as farm: raise ValueError # this will print # Closing # Traceback (most recent call last): # File "dummy.py", line 16, in <module> # raise ValueError # ValueError
This is turning into my own loud thinking and I think I get it now.
contextlib.closing() basically makes it possible to do what I did there with the
__exit__ and it seems the
file() built-in has a exit handler that takes care of the closing already so you don't have to do it with any extra decorators.