[Python-Dev] Iterator version of contextlib.nested

Hagen Fürstenau hfuerstenau at gmx.net
Mon Jun 15 10:11:51 CEST 2009


> Part of the justification for the new with-statement syntax was
> that nested() doesn't have a way to finalize the constructors
> if one of them fails.

I think the problem was a little bit more subtle: nested() gets passed
managers, so their __init__()s should all have run when the first
context is entered. The only problem comes up when the __exit__() of an
outer manager tries to suppress an exception raised by the __enter__()
of an inner one. This is a limited defect in that it doesn't affect the
common situation where no __exit__() tries to suppress any exceptions.
(In a quick glance over the std library I couldn't find a single
instance of an exception-suppressing __exit__().).

> And now
> that we have the new with-statement syntax, it mostly just
> represents a second-way-to-do-it (a second way that has
> has the stated pitfall).

So the functionalities of nested() and multi-with overlap in the common
use cases, and each has its own limitation in an uncommon one. I agree
that this situation is unfortunate, but I think introducing support for
one uncommon case and removing it for another is not the way to go in
3.1. That's why I think nested() should stay un-deprecated until there
is a replacement which handles a superset of its use cases.

> The new statement was not designed to support passing in
> tuples of context-managers.  This issue was raised while
> the new with-statement was being designed and it was
> intentionally left-out (in part, because the use cases were
> questionable

FWIW, my use case (which made me notice the DeprecationWarning in the
first place) is in a command dispatch function, which looks at the
command to be executed and pre-processes its arguments in a uniform way.
Part of that pre-processing is entering contexts of context manager
before passing them along (and exiting them when the command finishes or
raises an exception).

> and in-part because there were other ways
> to do it such as adding __enter__ and __exit__ to tuple).

Which has not been done for 3.1. Granted, you could subclass tuple and
add them yourself, but then you would mostly be copying what's already
implemented in nested().

> I suggest a PEP for 2.7 and 3.2 for building-out the
> with-statement to support tuples of context managers

That sounds like a good idea.

> IMO, this represents doing-it-the-right-way instead of preserving a
> construct that is known to be problematic.
> Leaving it in will enshrine it.

I don't see the problem with deprecating it only after a completely
suitable replacement is found. Why would it be any harder to deprecate
nested() in 3.2?

- Hagen



More information about the Python-Dev mailing list