假设您通过上下文管理器获取了三个对象,例如锁、数据库连接和 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
在 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(如下所述)。
ExitStack
contextlib.nested
contextlib2为 Python 2.6 和 2.7提供了向后移植。ExitStack
在 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()
请注意,这与通常使用 nested 并不完全相同with,因为A(),B()和C()最初都会在进入上下文管理器之前调用。如果这些函数之一引发异常,这将无法正常工作。
with
A()
B()
C()
contextlib.nested在较新的 Python 版本中已弃用,以支持上述方法。