Python’s “with” statement

Posted on April 22nd, 2011

Often when writing code I ran into situation where I set things up, do some work and then tear things down and clean up. This task is often achieved by setting up a series of try, except and finally statements within the code. Consider a simple case of retrieving some information from a text file.

try:
    f = open ('test.txt')
    data = f.read ()
finally:
    f.close ()

I’ve been thinking of wrapping this functionality into a decorator until I ran across a snippet of code that went something like this:

with open ('test.txt') as f:
    data = f.read ()

Nowhere in the code did it close the file making me rather curious. Turns out the “with” statement has been introduced in Python version 2.5 (PEP 343) to factor out the standard uses of try / finally logic.

Whats more you can build the necessary logic directly into your classes so that they can be used with the “with” statement. For example:

class Example ():
    def __enter__ (self):
        # Set things up here
        return obj
    def __exit__ (self, type, value, traceback):
        # Clean things up

with Example () as obj:
    # Do some related work

When you execute the code the __enter__ method gets called. If you passed the target along with the with statement the return value from the __enter__ method will be assigned to it. After your code block finishes executing the __exit__ method is called.

Note that if an error occurs in either the __enter__ method or your work code block the __exit__ method will be called and the exception type, value and traceback are passed into it as arguments, which allow you to handle the error intelligently. If no exception occurs then three None values are passed.

Pretty neat stuff!


Leave a Reply