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

问题描述

在 ,您可以编写:

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

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


在 ,可以使用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


在 ,您可以使用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版本中不推荐使用,而推荐使用上述方法

解决方法

假设您有三个通过上下文管理器获取的对象,例如一个锁,一个数据库连接和一个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

猜你在找的技术问答相关文章

如何检查配对的蓝牙设备是打印机还是扫描仪(Android)
是否允许实体正文进行HTTP DELETE请求?
如何将ZipInputStream转换为InputStream?
java.util.logging Java 8中的变量
PowerMockito.doReturn返回null
Java中的RESTful调用
Swing / Java:如何正确使用getText和setText字符串
特殊字符和重音字符
Android Studio中的ndk.dir错误
错误“找不到主类”