假设您通过上下文管理器获取了三个对象,例如锁、数据库连接和 ip 套接字。 您可以通过以下方式获得它们:
with lock:
with db_con:
with socket:
#do stuff
但是有没有办法在一个 block 中做到这一点?像
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
可能出现的问题(如下所述)。
contextlib2提供a backport of ExitStack
适用于 Python 2.6 和 2.7。
在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 版本中已弃用,以支持上述方法。
关于python - 在多个上下文管理器上创建一个 "with" block ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3024925/