是否可以在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)
......还是正在清理两个资源同时出现问题?
答案 0 :(得分:549)
可以在Python 3 since v3.1和Python 2.7中进行。新的with
syntax支持多个上下文管理器:
with A() as a, B() as b, C() as c:
doSomething(a,b,c)
与contextlib.nested
不同,这可以保证a
和b
即使__exit__()
或C()
也会__enter__()
被调用方法引发异常。
答案 1 :(得分:56)
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)
我想你想这样做:
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)
答案 3 :(得分: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似乎与此问题有关。
答案 4 :(得分:3)
从 Python 3.10 开始,Parenthesized context managers 有一个新特性,它允许使用以下语法:
with (
A() as a,
B() as b
):
do_something(a, b)
答案 5 :(得分:0)
在Python 3.1+中,您可以指定多个上下文表达式,它们的处理就像嵌套了多个main
语句一样:
foo
等同于
$PATH
这也意味着您可以在第二个表达式中使用第一个表达式的别名(在使用数据库连接/游标时很有用):
with
答案 6 :(得分: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
语句外部创建上下文管理器给人的印象是,创建的对象也可以在该语句外部进一步使用。如果对于您的上下文管理器不是这样,那么错误的印象可能与可读性尝试相对应。
大多数上下文管理器的编写方式意味着它们只能在with语句中有效使用一次。这些一次性使用的上下文管理器必须在每次使用时都重新创建-再次尝试使用它们会触发异常,否则将无法正常工作。
此常见限制意味着通常建议直接在使用with的with语句的标题中直接创建上下文管理器。