'with'语句中有多个变量?

时间:2009-05-21 14:51:27

标签: python with-statement

是否可以在Python中使用with语句声明多个变量?

类似的东西:

from __future__ import with_statement

with open("out.txt","wt"), open("in.txt") as file_out, file_in:
    for line in file_in:
        file_out.write(line)

......还是正在清理两个资源同时出现问题?

6 个答案:

答案 0 :(得分:549)

可以在Python 3 since v3.1Python 2.7中进行。新的with syntax支持多个上下文管理器:

with A() as a, B() as b, C() as c:
    doSomething(a,b,c)

contextlib.nested不同,这可以保证ab即使__exit__()C()也会__enter__()被调用方法引发异常。

答案 1 :(得分:56)

contextlib.nested支持此:

import contextlib

with contextlib.nested(open("out.txt","wt"), open("in.txt")) as (file_out, file_in):

   ...

<强>更新
引用文档,关于contextlib.nested

  

从版本2.7开始不推荐使用:with语句现在支持此功能   功能直接(没有容易出错的错误)。

有关详细信息,请参阅Rafał Dowgird's answer

答案 2 :(得分:18)

请注意,如果将变量分成几行,则必须使用反斜杠来包装换行符。

with A() as a, \
     B() as b, \
     C() as c:
    doSomething(a,b,c)

由于Python会创建一个元组,因此括号无效。

with (A(),
      B(),
      C()):
    doSomething(a,b,c)

由于元组缺少__enter__属性,因此会出现错误(描述性不强,无法识别类类型):

AttributeError: __enter__

如果您尝试在括号内使用as,Python会在解析时捕获错误:

with (A() as a,
      B() as b,
      C() as c):
    doSomething(a,b,c)
  

SyntaxError:语法无效

https://bugs.python.org/issue12782似乎与此问题有关。

答案 3 :(得分:18)

我想你想这样做:

from __future__ import with_statement

with open("out.txt","wt") as file_out:
    with open("in.txt") as file_in:
        for line in file_in:
            file_out.write(line)

答案 4 :(得分:0)

在Python 3.1+中,您可以指定多个上下文表达式,它们的处理就像嵌套了多个main语句一样:

foo

等同于

$PATH

这也意味着您可以在第二个表达式中使用第一个表达式的别名(在使用数据库连接/游标时很有用):

with

答案 5 :(得分:0)

您还可以separate创建上下文管理器(__init__方法)并输入上下文(__enter__方法)以提高可读性。因此,不用编写这段代码:

with Company(name, id) as company, Person(name, age, gender) as person, Vehicle(brand) as vehicle:
    pass

您可以编写以下代码:

company = Company(name, id)
person = Person(name, age, gender)
vehicle = Vehicle(brand)

with company, person, vehicle:
    pass

请注意,在with语句外部创建上下文管理器给人的印象是,创建的对象也可以在该语句外部进一步使用。如果对于您的上下文管理器不是这样,那么错误的印象可能与可读性尝试相对应。

documentation说:

大多数上下文管理器的编写方式意味着它们只能在with语句中有效使用一次。这些一次性使用的上下文管理器必须在每次使用时都重新创建-再次尝试使用它们会触发异常,否则将无法正常工作。

此常见限制意味着通常建议直接在使用with的with语句的标题中直接创建上下文管理器。