[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:
fout.write(fin.read())
Using contextlib.nested for that would be outright broken:
with nested(lock, open(infile), open(outfile) as (_, fin, fout):
fout.write(fin.read())
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):
fout.write(fin.read())
Of course, a custom context manager doesn't suffer any problems either:
@contextmanager
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):
fout.write(fin.read())
Cheers,
Nick.
[1] http://bugs.python.org/issue5491
--
Nick Coghlan | ncoghlan at gmail.com | Brisbane, Australia
---------------------------------------------------------------
More information about the Python-ideas
mailing list