wim*_*wim 4 python with-statement contextmanager
使用with语句,我们可以只使用一个级别的缩进/嵌套来输入许多上下文处理程序:
>>> from contextlib import contextmanager
>>> @contextmanager
... def frobnicate(n):
... print('frobbing {}'.format(n))
... yield
...
>>> frob1 = frobnicate(1)
>>> frob2 = frobnicate(2)
>>> with frob1, frob2:
... pass
...
frobbing 1
frobbing 2
Run Code Online (Sandbox Code Playgroud)
但这似乎不起作用:
>>> frobs = [frobnicate(1), frobnicate(2)]
>>> with *frobs:
... pass
# SyntaxError: invalid syntax
Run Code Online (Sandbox Code Playgroud)
我们如何输入n个上下文管理器而不必手动写出每个上下文管理器?
python2.7使用contextlib.nested来做到这一点,但由于容易出错的怪癖而被弃用.
这个函数有两个主要的怪癖,导致它被弃用.首先,作为上下文管理器都被构造在调用函数前,
__new__()和__init__()内上下文管理器的方法并不实际上由外上下文管理器的范围所覆盖.这意味着,例如,使用nested()打开两个文件是一个编程错误,因为如果在打开第二个文件时抛出异常,第一个文件将不会立即关闭.其次,如果
__enter__()其中一个内部上下文管理器的方法引发了一个由__exit__()外部上下文管理器的方法捕获和抑制的异常,则此构造将引发RuntimeError而不是跳过with语句的主体.
python3.3确实有一个更好的工作contextlib.ExitStack这将是这样的:
from contextlib import ExitStack
with ExitStack() as stack:
contexts = [stack.enter_context(frobnicate(i)) for i in range(2)]
...
Run Code Online (Sandbox Code Playgroud)
有关backport到python2.x代码,请参阅contextlib2.