问题描述
在 ,您可以编写:
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