A blog mostly about Python.

2010-03-08

Nested with statements in Python 3.1 are nice

Before Python 3.1 a convenient (but problematic) way of using nested with statements was to use the standard library provided context manager contextlib.nested. This context manager suggests that it can be used when writing code such as:
with contextlib.nested(A(), B()) as a, b:
    a.foo()
    b.foo()
As always, the devil is in the details. Since the the calls A() and B() occur before the nested context manager has been created the result of the code above is more like this:
a = A()
b = B()
with contextlib.nested(a, b):
    a.foo()
    b.foo()
This means that if an exception is raised when B() is executed the __exit__ method of a will never get called and we are now leaking resources.

Fortunately this has been fixed in Python 3.1 (and will also be in 2.7 I believe). From now on support for nested with statements is in the Python language it self. Instead of using contextlib.nested we can now do this:
with A() as a, B() as b:
    a.foo()
    b.foo()
And this really is equivalent to two nested with statements:
with A() as a:
    with b() as b:
        a.foo()
        b.foo()
Nice, I say!

1 comment:

  1. I have scene this code on several sites. One even showed a simple timer class, using a enter and exit method. Are there other examples? This could be wickedly useful.

    ReplyDelete

Followers