如果我可以写入所有文件,我想同时更改几个文件。 我想知道是否可以使用with
语句组合多个打开调用:
try:
with open('a', 'w') as a and open('b', 'w') as b:
do_something()
except IOError as e:
print 'Operation failed: %s' % e.strerror
如果不可能实现这个,那么解决该问题的优雅方案是什么?
如果我可以写入所有文件,我想同时更改几个文件。 我想知道是否可以使用with
语句组合多个打开调用:
try:
with open('a', 'w') as a and open('b', 'w') as b:
do_something()
except IOError as e:
print 'Operation failed: %s' % e.strerror
如果不可能实现这个,那么解决该问题的优雅方案是什么?
从Python 2.7(或3.1)开始,您可以编写:
with open('a', 'w') as a, open('b', 'w') as b:
do_something()
(历史注释:在早期版本的Python中,有时可以使用contextlib.nested()
来嵌套上下文管理器。然而,这对于打开多个文件并非如预期般有效--请查看相关文档以了解详情。)
在极少数情况下,如果您想要同时打开数量可变的文件,您可以从Python 3.3开始使用contextlib.ExitStack
:
with ExitStack() as stack:
files = [stack.enter_context(open(fname)) for fname in filenames]
# Do something with "files"
请注意,通常情况下,您希望按顺序处理文件,而不是同时打开所有文件,特别是如果您有数量可变的文件:
for fname in filenames:
with open(fname) as f:
# Process f
with
打开一个变量列表的文件吗? - monkutExitStack
。(http://docs.python.org/3/library/contextlib.html#contextlib.ExitStack)在任何早期版本的Python中都没有简单的方法来实现这一点。 - Sven Marnach只需要将and
替换为,
即可完成:
try:
with open('a', 'w') as a, open('b', 'w') as b:
do_something()
except IOError as e:
print 'Operation failed: %s' % e.strerror
为了一次打开多个文件或者处理很长的文件路径,将代码分成多行可能会很有用。来自Python风格指南,建议按照@Sven Marnach在另一个答案的评论中提到的方式操作:
with open('/path/to/InFile.ext', 'r') as file_1, \
open('/path/to/OutFile.ext', 'w') as file_2:
file_2.write(file_1.read())
从Python 3.10开始,出现了一个名为“括号内的上下文管理器”的新特性,它允许类似以下语法的操作:
with (
open("a", "w") as a,
open("b", "w") as b
):
do_something()
with open("a", "w") as a, open ("b", "w") as b:
无法做到的吗? - PatrickTcontextlib
模块中的ExitStack
类安全地打开任意数量的文件。它可以管理动态数量的上下文感知对象,这意味着如果您不知道要处理多少个文件,它将特别有用。实际上,文档中提到的典型用例是管理动态数量的文件。with ExitStack() as stack:
files = [stack.enter_context(open(fname)) for fname in filenames]
# All opened files will automatically be closed at the end of
# the with statement, even if attempts to open files later
# in the list raise an exception
如果你对细节感兴趣,这里有一个通用的例子来解释ExitStack
是如何操作的:
from contextlib import ExitStack
class X:
num = 1
def __init__(self):
self.num = X.num
X.num += 1
def __repr__(self):
cls = type(self)
return '{cls.__name__}{self.num}'.format(cls=cls, self=self)
def __enter__(self):
print('enter {!r}'.format(self))
return self.num
def __exit__(self, exc_type, exc_value, traceback):
print('exit {!r}'.format(self))
return True
xs = [X() for _ in range(3)]
with ExitStack() as stack:
print(len(stack._exit_callbacks)) # number of callbacks called on exit
nums = [stack.enter_context(x) for x in xs]
print(len(stack._exit_callbacks))
print(len(stack._exit_callbacks))
print(nums)
输出:
0
enter X1
enter X2
enter X3
3
exit X3
exit X2
exit X1
0
[1, 2, 3]
使用嵌套的with语句可以完成同样的工作,而且在我看来更加直观易懂。
假设您有inFile.txt,并想同时将其写入两个outFile中。
with open("inFile.txt", 'r') as fr:
with open("outFile1.txt", 'w') as fw1:
with open("outFile2.txt", 'w') as fw2:
for line in fr.readlines():
fw1.writelines(line)
fw2.writelines(line)
编辑:
我不理解为什么会被踩。在发布回答之前,我测试了我的代码,并且它按照要求将内容写入了所有的outFile中。没有重复写入或未能写入。因此,我真的很想知道为什么我的答案被认为是错误的、次优的或其他类似的东西。
ExitStack
是合适的。我喜欢这种明确的方式,但如果函数在其输入中执行更多操作,则会将第四个级别包装在单独的函数fanout(fr,fw1,fw2)
中以重置缩进,特别是在示例中未显示的情况下。 - ojdo在Python 2.6版本中,这种方法不可行。我们需要使用以下方式来打开多个文件:
with open('a', 'w') as a:
with open('b', 'w') as b:
def multi_open(_list):
out=""
for x in _list:
try:
with open(x) as f:
out+=f.read()
except:
pass
# print(f"Cannot open file {x}")
return(out)
fl = ["C:/bdlog.txt", "C:/Jts/tws.vmoptions", "C:/not.exist"]
print(multi_open(fl))
2018-10-23 19:18:11.361 PROFILE [Stop Drivers] [1ms]
2018-10-23 19:18:11.361 PROFILE [Parental uninit] [0ms]
...
# This file contains VM parameters for Trader Workstation.
# Each parameter should be defined in a separate line and the
...