将上下文管理器的动态可迭代链接到单个 with 语句
Chain dynamic iterable of context managers to a single with statement
我有一堆要链接的上下文管理器。乍一看,contextlib.nested
看起来是一个合适的解决方案。但是,此方法在文档中被标记为已弃用,该文档还指出最新的 with
语句直接允许这样做:
Deprecated since version 2.7: The with-statement now supports this
functionality directly (without the confusing error prone quirks).
但是我无法让 Python 3.4.3 使用上下文管理器的动态迭代:
class Foo():
def __enter__(self):
print('entering:', self.name)
return self
def __exit__(self, *_):
pass
def __init__(self, name):
self.name = name
foo = Foo('foo')
bar = Foo('bar')
是否链接:
from itertools import chain
m = chain([foo], [bar])
with m:
pass
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: __exit__
m = [foo, bar]
直接提供列表:
with m:
pass
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: __exit__
或解包:
with (*m):
pass
File "<stdin>", line 1
SyntaxError: can use starred expression only as assignment target
那么,如何在 with
语句中正确链接动态数量的上下文管理器?
"multiple manager form of the with
statement",如 the statement's documentation 所示,将是:
with foo, bar:
即它不 支持动态数量的经理。正如 the documentation for contextlib.nested
所说:
Developers that need to support nesting of a variable number of
context managers can either use the warnings
module to suppress the
DeprecationWarning
raised by this function or else use this function
as a model for an application specific implementation.
你误解了那句话。 with
语句采用多个上下文管理器,以逗号分隔,但 不是 可迭代的:
with foo, bar:
有效。
如果需要支持 动态 上下文管理器集,请使用 contextlib.ExitStack()
object:
from contextlib import ExitStack
with ExitStack() as stack:
for cm in (foo, bar):
stack.enter_context(cm)
我有一堆要链接的上下文管理器。乍一看,contextlib.nested
看起来是一个合适的解决方案。但是,此方法在文档中被标记为已弃用,该文档还指出最新的 with
语句直接允许这样做:
Deprecated since version 2.7: The with-statement now supports this functionality directly (without the confusing error prone quirks).
但是我无法让 Python 3.4.3 使用上下文管理器的动态迭代:
class Foo():
def __enter__(self):
print('entering:', self.name)
return self
def __exit__(self, *_):
pass
def __init__(self, name):
self.name = name
foo = Foo('foo')
bar = Foo('bar')
是否链接:
from itertools import chain
m = chain([foo], [bar])
with m:
pass
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: __exit__
m = [foo, bar]
直接提供列表:
with m:
pass
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: __exit__
或解包:
with (*m):
pass
File "<stdin>", line 1
SyntaxError: can use starred expression only as assignment target
那么,如何在 with
语句中正确链接动态数量的上下文管理器?
"multiple manager form of the with
statement",如 the statement's documentation 所示,将是:
with foo, bar:
即它不 支持动态数量的经理。正如 the documentation for contextlib.nested
所说:
Developers that need to support nesting of a variable number of context managers can either use the
warnings
module to suppress theDeprecationWarning
raised by this function or else use this function as a model for an application specific implementation.
你误解了那句话。 with
语句采用多个上下文管理器,以逗号分隔,但 不是 可迭代的:
with foo, bar:
有效。
如果需要支持 动态 上下文管理器集,请使用 contextlib.ExitStack()
object:
from contextlib import ExitStack
with ExitStack() as stack:
for cm in (foo, bar):
stack.enter_context(cm)