编程语言
首页 > 编程语言> > python – 如何__enter__ n上下文管理器?

python – 如何__enter__ n上下文管理器?

作者:互联网

使用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

但这似乎不起作用:

>>> frobs = [frobnicate(1), frobnicate(2)]
>>> with *frobs:
...     pass
# SyntaxError: invalid syntax

我们如何输入n个上下文管理器而不必手动写出每个上下文管理器?

解决方法:

python2.7让contextlib.nested做到了这一点,但由于容易出错的怪癖而被弃用.

This function has two major quirks that have led to it being deprecated. Firstly, as the context managers are all constructed before the function is invoked, the __new__() and __init__() methods of the inner context managers are not actually covered by the scope of the outer context managers. That means, for example, that using nested() to open two files is a programming error as the first file will not be closed promptly if an exception is thrown when opening the second file.

Secondly, if the __enter__() method of one of the inner context managers raises an exception that is caught and suppressed by the __exit__() method of one of the outer context managers, this construct will raise RuntimeError rather than skipping the body of the with statement.

python3.3使用contextlib.ExitStack做得更好,看起来像:

from contextlib import ExitStack

with ExitStack() as stack:
    contexts = [stack.enter_context(frobnicate(i)) for i in range(2)]
    ...

有关backport到python2.x代码,请参阅contextlib2.

标签:python,with-statement,contextmanager
来源: https://codeday.me/bug/20190528/1172311.html