繁体   English   中英

如何在 Python 中使用“with open”打开多个文件?

[英]How can I open multiple files using "with open" in Python?

我想一次更改几个文件,如果我可以写入所有文件。 我想知道我是否可以将多个 open 调用与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()来嵌套上下文管理器。 但是,这在打开多个文件时不会按预期工作 - 有关详细信息,请参阅链接的文档。


在极少数情况下,您想同时打开可变数量的文件,您可以使用contextlib.ExitStack ,从 Python 3.3 版开始:

with ExitStack() as stack:
    files = [stack.enter_context(open(fname)) for fname in filenames]
    # Do something with "files"

大多数情况下,您有一组可变的文件,但您可能希望一个接一个地打开它们。

只需将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

对于一次打开多个文件或长文件路径,将内容分成多行可能很有用。 从@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())

嵌套语句会做同样的工作,在我看来,处理起来更直接。

假设您有 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 3.3,你可以使用类ExitStackcontextlib模块安全
打开任意数量的文件

它可以管理动态数量的上下文感知对象,这意味着如果您不知道要处理多少个文件,它将特别有用。

事实上,文档中提到的规范用例是管理动态数量的文件。

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]

从 Python 3.10 开始,有括号上下文管理器的新特性,它允许使用如下语法:

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

使用 python 2.6 不行,我们必须使用下面的方式打开多个文件:

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

迟到的答案(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
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM