为了账号安全,请及时绑定邮箱和手机立即绑定

在几个上下文管理器上创建一个“with”块?

在几个上下文管理器上创建一个“with”块?

饮歌长啸 2019-08-27 11:01:02
在几个上下文管理器上创建一个“with”块?假设您有三个通过上下文管理器获取的对象,例如A锁,数据库连接和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
查看完整描述

3 回答

?
犯罪嫌疑人X

TA贡献2080条经验 获得超4个赞

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为Python 2.6和2.7 提供了一个反向移植ExitStack


Python 2.6及更低版本中,您可以使用contextlib.nested

from contextlib import nestedwith 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版本中不赞成使用上述方法。


查看完整回答
反对 回复 2019-08-27
?
海绵宝宝撒

TA贡献1809条经验 获得超8个赞

您可以在Python 3.1中提出问题的第一部分。

如果有多个项目,则会处理上下文管理器,就好像多个with语句嵌套一样:

with A() as a, B() as b:
    suite

相当于

with A() as a:
    with B() as b:
        suite

在3.1版中更改:支持多个上下文表达式


查看完整回答
反对 回复 2019-08-27
  • 3 回答
  • 0 关注
  • 438 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信