[Python-ideas] A real limitation of contextlib.nested()

Nick Coghlan ncoghlan at gmail.com
Sun Mar 15 05:58:38 CET 2009

I missed the discussion about potentially adding syntactic support for
multiple context managers in the with statement, but figured I should
mention a real limitation of contextlib.nested that *would* be fixed by
adding dedicated syntactic support.

There's a genuine semantic difference between this:

  with cmA():
      with cmB():
          # whatever

and this:

  with nested(cmA(), cmB()):
      # whatever

The latter is actually more accurately translated as:

  mgr1, mgr2 = cmA(), cmB():
  with mgr1:
      with mgr2:
          # whatever

That is, when using nested() the later context managers are created
outside the scope of the earlier context managers.

So, to use Christian's example from the previous discussion:

  with lock:
      with open(infile) as fin:
          with open(outfile, 'w') as fout:

Using contextlib.nested for that would be outright broken:

  with nested(lock, open(infile), open(outfile) as (_, fin, fout):

1. The files are opened without acquiring the lock first
2. If an IOError is raised while opening "outfile", then "infile"
doesn't get closed immediately

I created issue 5491 [1] to point out that the contextlib.nested docs
could do with being tweaked to make this limitation clearer.

Dedicated syntax (such as the form that Christian proposed) would fix
this problem:

  with lock, (open(infile) as fin), (open(outfile, 'w') as fout):

Of course, a custom context manager doesn't suffer any problems either:

    def synced_io(lock, infile, outfile):
        with lock:
            with open(infile) as fin:
                with open(outfile) as fout:
                    yield fin, fout

    with synced_io(lock, infile, outfile) as (fin, fout):


[1] http://bugs.python.org/issue5491

Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia

More information about the Python-ideas mailing list