I have an iterator that returns context managers.
I want a pythonic with
statement, that emulates the behaviour of several nested with
statements, one for each context manager returned by the iterator.
One could say, I want a generalisation of the (deprecated) contextlib.nested
function.
contextlib.nested
has two major problems that caused it to be deprecated.__init__
or__new__
, and these exceptions would cause the whole with statement to abort without calling__exit__
of the outer manager.True
in__exit__
, the block should still be executed. But in the implementation ofnested
, it just raises aRuntimeError
without executing the block. This problem probably requires a total rewrite ofnested
.But it is possible to solve the first problem by just removing one
*
in the definition ofnested
! This changes the behaviour such thatnested
doesn't accept argument lists anymore (which isn't useful anyway becausewith
can handle that already) but only an iterator. I therefore call the new version "iter_nested
". The user can then define an iterator that instantiates the context managers during iteration.An example with a generator:
The difference between the codes of the original and my changed version of
nested
is here:This implementation - or something more or less like this, should make what the late contextçlib.nested used to do, but taking care of the already entered contexts if an exception is raised when entering a new context.
Contexts can be passed to it either as a context-protocol object, or as a tuple, where the first member is a called object that will be called with the remainder of the tuple as parameters, in a managed environment:
From the docs:
The difficult thing about handling multiple context managers is that they interact non-trivially: for example, you might
__enter__
the first then raise an exception in__enter__
ing the second. These sort of edge cases are precisely what causednested
to be deprecated. If you want to support them, you will have to think very carefully about how you write your code. You may wish to read PEP-0343 for ideas.