当我处理一个文件时,我可以使用with
语句来确保它在成功或失败时始终关闭。如
with open('some_file', 'r') as f:
print f.read()
但是,我现在需要打开一个文件列表,其数量仅在运行时已知,因此我不能使用嵌套的语句。但是我可以将它与列表一起使用吗?有点像
with [open(fn) for fn in file_names] as files:
#do something
以上显然不起作用。什么会起作用?
答案 0 :(得分:1)
这正是contextlib
模块的contextlib.nested
管理器的设计目标。您可以像这样使用它:
from contextlib import nested
with nested(*[open(fn) for fn in file_names]) as files:
# files is a list of file objects
但请注意,正如documentation中所述,自Python2.7以来,该函数已被弃用,原因有两个怪癖。我会让你判断你是否可以在你想到的应用程序中与他们一起生活。
我认为这也是提及with
声明解释here的鲜为人知的多管理员表单的好时机。即使它不适用于您的情况,我认为知道它存在是很好的。
答案 1 :(得分:1)
正如@Marcin在评论中提到的那样,我认为没有办法使用列表with
来实现这一点。
但是,对于一组允许封装的try
/ except
/ finally
块,with
基本上是语法糖,因此更容易重用。
虽然您可以在单个with
中指定多个配对,即
with open('foo.txt', 'r') as f, open('bar.txt', 'r') as f2:
pass # do stuff here
动态变量没有允许,例如list
s或tuple
s。实际上,此表单被视为以逗号分隔的表达式嵌套with
s。
但是,您可以做的事实上是忽略with
的语法糖,并依赖于它要替换的原始语法。也就是说,将您的逻辑封装在一组try
/ except
/ finally
块中。这样,您可以在运行时打开文件列表,然后通过finally
子句确保它们得到清理。
某种形式:
try:
files = [open(fn) for fn in file_names]
# do stuff with files
except:
# handle exceptions as needed here
finally:
for f in files:
f.close();
# and any other cleanup you want to do