我有一个返回上下文管理器的迭代器。
I have an iterator that returns context managers.
我想要一个带有语句的pythonic 语句,它模拟了几个嵌套的带有语句的行为,迭代器返回的每个上下文管理器都有一个。
I want a pythonic with statement, that emulates the behaviour of several nested with statements, one for each context manager returned by the iterator.
可以说,我想要推广(已弃用) contextlib.nested 函数。
One could say, I want a generalisation of the (deprecated) contextlib.nested function.
推荐答案contextlib.nested 有两个主要问题导致它被弃用。
contextlib.nested has two major problems that caused it to be deprecated.
但这是可能的通过在嵌套的定义中删除一个 * 来解决第一个问题! 这改变了行为,使得嵌套不再接受参数列表(这无论如何都没用,因为带有已经可以处理了)但只有一个迭代器。因此,我将新版本称为 iter_nested 。 然后,用户可以定义迭代器,在迭代期间实例化上下文管理器。
But it is possible to solve the first problem by just removing one * in the definition of nested! This changes the behaviour such that nested doesn't accept argument lists anymore (which isn't useful anyway because with 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.
生成器的示例:
def contexts(): yield MyContext1() yield MyContext2() with iter_nested(contexts()) as contexts: do_stuff(contexts[0]) do_other_stuff(contexts[1])原始代码与我更改的嵌套版本之间的差异在于:
The difference between the codes of the original and my changed version of nested is here:
from contextlib import contextmanager @contextmanager --- def nested(*managers): +++ def iter_nested(mgr_iterator): --- #comments & deprecation warning exits = [] vars = [] --- exc = (None, None, None) +++ exc = None # Python 3 try: --- for mgr in managers: +++ for mgr in mgr_iterator: exit = mgr.__exit__ enter = mgr.__enter__ vars.append(enter()) exits.append(exit) yield vars # All of the following is new and fit for Python 3 except Exception as exception: exc = exception exc_tuple = (type(exc), exc, exc.__traceback__) else: exc_tuple = (None, None, None) finally: while exits: exit = exits.pop() try: if exit(*exc_tuple): exc = None exc_tuple = (None, None, None) except Exception as exception: exception.__context__ = exc exc = exception exc_tuple = (type(exc), exc, exc.__traceback__) if exc: raise exc更多推荐
将Python上下文管理器的迭代器嵌套在“with”中
发布评论