ola*_*ndo 180 python with-statement contextmanager
假设您有三个通过上下文管理器获取的对象,例如A锁,数据库连接和ip套接字.您可以通过以下方式获取它
with lock:
with db_con:
with socket:
#do stuff
Run Code Online (Sandbox Code Playgroud)
但有没有办法在一个街区内完成?就像是
with lock,db_con,socket:
#do stuff
Run Code Online (Sandbox Code Playgroud)
此外,如果有一组具有上下文管理器的未知长度的对象,是否有可能以某种方式做到:
a=[lock1, lock2, lock3, db_con1, socket, db_con2]
with a as res:
#now all objects in array are acquired
Run Code Online (Sandbox Code Playgroud)
如果答案是"不",是不是因为需要这样的功能意味着设计不好,或者我应该建议它?:-P
int*_*jay 319
在Python 2.7和3.1及更高版本中,您可以编写:
with A() as X, B() as Y, C() as Z:
do_something()
Run Code Online (Sandbox Code Playgroud)
这通常是最好的方法,但是如果你有一个未知长度的上下文管理器列表,你将需要以下方法之一.
在Python 3.3中,您可以使用contextlib.ExitStack输入未知长度的上下文管理器列表:
with ExitStack() as stack:
for mgr in ctx_managers:
stack.enter_context(mgr)
# ...
Run Code Online (Sandbox Code Playgroud)
这允许您在将上下文管理器添加到上下文管理器时创建上下文管理器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()
Run Code Online (Sandbox Code Playgroud)
相当于:
m1, m2, m3 = A(), B(), C()
with m1 as X:
with m2 as Y:
with m3 as Z:
do_something()
Run Code Online (Sandbox Code Playgroud)
请注意,这是不完全的正常使用嵌套相同with,因为A(),B()和C()都将最初称,进入上下文经理之前.如果其中一个函数引发异常,则无法正常工作.
contextlib.nested 在较新的Python版本中不赞成使用上述方法.
Mar*_*ers 25
您可以在Python 3.1中提出问题的第一部分.
如果有多个项目,则会处理上下文管理器,就好像多个with语句嵌套一样:
Run Code Online (Sandbox Code Playgroud)with A() as a, B() as b: suite相当于
Run Code Online (Sandbox Code Playgroud)with A() as a: with B() as b: suite在3.1版中更改:支持多个上下文表达式
sag*_*e88 18
@ interjay的答案是对的.但是,如果您需要为长期上下文管理器(例如mock.patch上下文管理器)执行此操作,那么您很快就会意识到要跨行分解.事实证明你不能将它们包裹在parens中,所以你必须使用反斜杠.这是看起来像:
with mock.patch('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa') as a, \
mock.patch('bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb') as b, \
mock.patch('cccccccccccccccccccccccccccccccccccccccccc') as c:
do_something()
Run Code Online (Sandbox Code Playgroud)