将上下文管理器的动态可迭代链接到单个with语句

将上下文管理器的动态可迭代链接到单个with语句

本文介绍了将上下文管理器的动态可迭代链接到单个with语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一堆要链接的上下文管理器.乍一看,contextlib.nested看起来很合适.但是,该方法在文档中被标记为已弃用,该文档还指出最新的with语句直接允许这样做:

I have a bunch of context managers that I want to chain. On the first glance, contextlib.nested looked like a fitting solution. However, this method is flagged as deprecated in the documentation which also states that the latest with statement allows this directly:

但是我无法让Python 3.4.3使用上下文管理器的动态迭代:

However I could not get Python 3.4.3 to use a dynamic iterable of context managers:

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语句中正确链接动态数量的上下文管理器?

So, how do I properly chain a dynamic amount of context managers in a with statement correctly?

推荐答案

您误解了这一行. with语句使用多个上下文管理器,以逗号分隔,但不是可迭代:

You misunderstood that line. The with statement takes more than one context manager, separated by commas, but not an iterable:

with foo, bar:

有效.

如果需要,使用 contextlib.ExitStack()对象支持一组 dynamic 上下文管理器:

Use a contextlib.ExitStack() object if you need to support a dynamic set of context managers:

from contextlib import ExitStack

with ExitStack() as stack:
    for cm in (foo, bar):
        stack.enter_context(cm)

这篇关于将上下文管理器的动态可迭代链接到单个with语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 23:41