Python etc / Nested context managers

Nested context managers

Sometimes you want to run a code block with multiple context managers:

with open('f') as f:
    with open('g') as g:
        with open('h') as h:
            pass

Since Python 2.7 and 3.1, you can do it with a single with expression:

o = open
with o('f') as f, o('g') as g, o('h') as h:
    pass

Before that, you could you use the contextlib.nested function:

with nested(o('f'), o('g'), o('h')) as (f, g, h):
    pass

It still can be used while working with an unknown number of context managers (nested(*managers)), but it throws the warning in the modern Python interpreter.

Instead, the more advanced tool is provided. contextlib.ExitStack allows you to enter any number of contexts at the arbitrary time but guarantees to exit them at the end:

with ExitStack() as stack:
    f = stack.enter_context(o('f'))
    g = stack.enter_context(o('g'))
    other = [
        stack.enter_context(o(filename))
        for filename in filenames
    ]