多行上的Python嵌套上下文管理器

Sim*_*ias 23 python with-statement contextmanager

在Python 2.6中,我们使用以下方式格式化嵌套上下文管理器:

with nested(
    context1,
    context2
) as a, b:
    pass
Run Code Online (Sandbox Code Playgroud)

从Python 2.7开始,nested不推荐使用.我在一行上看到了很多关于多个上下文管理器的例子,但我找不到允许它们在多行上的语法.你会怎么做?

# That's working fine
with context1 as a, context2 as b:
    pass

# But how do we make it multine?
# These are not working
with (
    context1,
    context2
) as a, b:
    pass

with context1 as a,
    context2 as b:
    pass
Run Code Online (Sandbox Code Playgroud)

vau*_*tah 25

反斜杠字符

可以使用反斜杠字符(\)将两条或更多条物理线连接到逻辑行中

(引用显式行加入部分)

如果您希望将上下文管理器放在不同的行上,您可以通过使用反斜杠结束行来实现这一点:

with context1 as a,\
     context2 as b:
    pass
Run Code Online (Sandbox Code Playgroud)

contextlib.ExitStack

contextlib.ExitStack 是一个

上下文管理器,旨在使其易于以编程方式组合其他上下文管理器和清理功能,尤其是那些可选或由输入数据驱动的功能.

它在Python 3.3及更高版本中可用,并允许轻松输入可变数量的上下文管理器.对于两个上下文管理器,用法如下所示:

from contextlib import ExitStack

with ExitStack() as es:
    a = es.enter_context(context1)
    b = es.enter_context(context2)
Run Code Online (Sandbox Code Playgroud)

嵌套

可以跨多个嵌套 with语句拆分上下文表达式:

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

with A() as a, B() as b:
Run Code Online (Sandbox Code Playgroud)

套房相当于

with A() as a:
    with B() as b:
        suite
Run Code Online (Sandbox Code Playgroud)

(来自with声明)

  • 这是唯一的语法 - 因为它非常难看...... :( (7认同)
  • 不敢相信我说的是,但在这种情况下,与lisp相比,python语法很糟糕.(let)或其他绑定形式的多个赋值看起来完全自然......但这很尴尬. (3认同)

900*_*000 8

有一种方法可以创造性地使用括号并避免使用反斜杠:先将表达式括起来as.但不是很明显:

with (
  open('/etc/passwd')) as foo, (
  open('/tmp/bar')) as bar:
  pass  # this parses correctly
Run Code Online (Sandbox Code Playgroud)

如果需要,可以更容易地嵌套.

  • 为什么你想在这种情况下避免使用反斜杠?开放的parens在这里发挥着基本相同的作用,但它也变得更加神秘. (2认同)
  • @isarandi:反斜线作为行的延续在编辑时比其他东西更容易打破。PEP-8建议使用括号,以反斜杠继续。顺便说一句,同一PEP-8建议对多个“ with”语句使用“ \”。我个人更喜欢`with`的嵌套,但是为了完整起见添加了这个答案。 (2认同)