我想一次更改几个文件,如果我可以写入所有文件。我想知道我是否可以将多个打开的调用与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

如果这是不可能的,那么这个问题的优雅解决方案是什么样子的?


当前回答

迟交答案(8岁),但对于希望将多个文件合并为一个文件的人,以下功能可能会有所帮助:

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
...

其他回答

对于一次打开多个文件或对于长文件路径,在多行上拆分可能很有用。从@Sven Marnach在评论中建议的Python风格指南到另一个答案:

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()

嵌套语句也会起到同样的作用,而且在我看来,处理起来更简单。

假设您有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。无重复书写或未能书写。所以我很想知道为什么我的答案被认为是错误的、次优的或类似的。

对于python 2.6,它将无法工作,我们必须使用以下方式打开多个文件:

with open('a', 'w') as a:
    with open('b', 'w') as b:

从Python 2.7(或3.1)开始,您可以编写

with open('a', 'w') as a, open('b', 'w') as b:
    do_something()

(历史注释:在早期版本的Python中,有时可以使用contextlib.nested()来嵌套上下文管理器。但是,对于打开多个文件来说,这不会像预期的那样奏效——请参阅链接文档以了解详细信息。)


在罕见的情况下,您希望同时打开可变数量的文件,可以使用contextlib.ExitStack,从Python版本3.3开始:

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