小编典典

在多个上下文管理器上创建一个“ with”块?[重复]

python

这个问题已经在这里有了答案

“ with”语句中有多个变量? (7个答案)

2年前关闭。

假设您有三个通过上下文管理器获取的对象,例如一个锁,一个数据库连接和一个IP套接字。您可以通过以下方式获取它们:

with lock:
   with db_con:
       with socket:
            #do stuff

但是,有一种方法可以一次完成吗?就像是

with lock,db_con,socket:
   #do stuff

此外,有可能给定具有上下文管理器的对象长度未知的数组,是否有可能这样做:

a=[lock1, lock2, lock3, db_con1, socket, db_con2]
with a as res:
    #now all objects in array are acquired

如果答案为“否”,是否是因为对这种功能的需求暗示了不良的设计,或者我应该在一秒钟内建议它?:-P


阅读 51

收藏
2020-12-20

共1个答案

小编典典

Python 2.7和3.1及更高版本中 ,您可以编写:

with A() as X, B() as Y, C() as Z:
    do_something()

通常,这是最好的使用方法,但是如果上下文管理器列表的长度未知,则需要以下方法之一。


Python 3.3中
,可以使用contextlib.ExitStack输入未知长度的上下文管理器列表:

with ExitStack() as stack:
    for mgr in ctx_managers:
        stack.enter_context(mgr)
    # ...

这样,您可以在将上下文管理器添加到中时创建上下文管理器ExitStack,以防止可能的问题contextlib.nested(如下所述)。

contextlib2为Python
2.6和2.7提供了backportExitStack


Python 2.6及以下版本中
,您可以使用contextlib.nested

from contextlib import nested

with nested(A(), B(), C()) as (X, Y, Z):
    do_something()

等效于:

m1, m2, m3 = A(), B(), C()
with m1 as X:
    with m2 as Y:
        with m3 as Z:
            do_something()

请注意,这是不完全的正常使用嵌套相同with,因为A()B()C()都将最初称,进入上下文经理之前。如果这些功能之一引发异常,则将无法正常工作。

contextlib.nested 在较新的Python版本中不推荐使用,而推荐使用上述方法。

2020-12-20