python:在几个上下文pipe理器上创build一个“with”块
假设您有三个通过上下文pipe理器获取的对象,例如A锁,一个数据库连接和一个IP套接字。 你可以通过以下方式获得
with lock: with db_con: with socket: #do stuff 但有一种方法可以在一个区块内完成吗? 就像是
 with lock,db_con,socket: #do stuff 
而且,有可能的话,给定一组具有上下文pipe理器的未知长度的对象,有可能以某种方式进行:
 a=[lock1, lock2, lock3, db_con1, socket, db_con2] with a as res: #now all objects in array are acquired 
如果答案是“否”,是不是因为需要这样的function意味着devise不好,或者我应该提出一个build议呢? 😛
  在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() 
 请注意,这与通常使用嵌套的不完全相同,因为在进入上下文pipe理器之前, A() , B()和C()都将被初始调用。 如果这些函数中的一个可能引发exception,这将无法正常工作,但将用于问题中的示例。 
  在Python 2.7和3.1中 ,为此添加了语法,并且已经不赞成使用contextlib.nested : 
 with A() as X, B() as Y, C() as Z: do_something() 
在Python 3.3中 ,你也可以通过使用contextlib.ExitStack来input未知长度的上下文pipe理器列表:
 with ExitStack() as stack: for mgr in ctx_managers: stack.enter_context(mgr) # ... 
 这允许您创build上下文pipe理器,因为您将它们添加到ExitStack ,从而避免了ExitStack可能出现的问题。 
你的问题的第一部分可能在Python 3.1中 。
对于多个项目,上下文pipe理器将被处理,就好像多个语句是嵌套的一样:
with A() as a, B() as b: suite相当于
with A() as a: with B() as b: suite在版本3.1中更改 :支持多个上下文expression式
 你的问题的第二部分是用Python 3.3中的 contextlib.ExitStack解决的。 
@ interjay的答案是正确的。 但是,如果您需要为长时间的上下文pipe理器执行此操作,例如mock.patch上下文pipe理器,那么您很快就会意识到您希望跨越这些线程来打破这种情况。 原来,你不能把它们包装在parens中,所以你必须使用反斜杠。 以下是这个样子:
 with mock.patch('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') as a, \ mock.patch('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb') as b, \ mock.patch('cccccccccccccccccccccccccccccccccccccccccc') as c: do_something()