
Do you train Kung Fu?
Or know someone who does?
Then check out KungFuPeople.com
Mobile version of this pageIntegrate BrowserID in a Tornado web app
Next:
Cryptic errors when using django-nose
Related by category
Python file with closing automatically
2nd of 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:
try:
dest.write('stuff')
finally:
dest.close()
print open('foo').read() # will print 'stuff'
We can use this:
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:
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 closing() decrorator:
def close(self):
print "Closing"
from contextlib import closing
with closing(Farm()) as farm:
pass
# this will print:
# Closing
So the closing() decorator "steals" the __enter__ and __exit__. This last one can be handy if you do this:
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 __enter__ and __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.


Correct, contextlib.closing() is just an adapter that maps the context management protocol (i.e. __enter__/__exit__) to any object with a close() method. It's most useful when you can't readily alter the original definition of the objects involved.
If an object already supports the context management protocol directly (which includes most* file-like objects in the standard library), then you don't need the adapter.
(*if we've missed any, then feature requests to fix that are usually looked on quite favourably)