【问题标题】:How to "with open" a list of files and obtain their handles in python? [duplicate]如何“打开”文件列表并在python中获取它们的句柄? [复制]
【发布时间】:2016-09-30 02:46:44
【问题描述】:

是否可以with open()列表中包含的所有文件并创建文件句柄以进行写入?

例如,如果我的函数在机器学习任务中接受用于数据拆分的文件名列表,

fname_list = ['train_dataset.txt', 'validate_dataset.txt', 'test_dataset.txt']

那么能做到就方便了:

with open('source_dataset.txt) as src_file, open(name_list, 'w') as <DONT_KNOW_WHAT_TO_DO_HERE>:

并在块内执行一些数据拆分。

编辑:所以我的问题基本上是“是否可以为使用 'with open()' 打开的文件列表获取多个文件句柄?”

【问题讨论】:

  • 我不确定如何为文件列表创建多个文件句柄。 ...open(name_list, 'w') as :
  • 为什么不遍历文件名列表,打开并读取它们,并将每个文件名的字符串数据存储在一个列表中以供以后使用?
  • 由于数据集可能包含数百万行,这样做不会将开销增加到 (100 万) x len(list_of_filenames) 吗?或者也许这是一些我不应该担心的优化?
  • 好吧。只需遍历文件名列表,然后打开每个文件。然后用那个文件做你的生意。无论是阅读文字还是其他。
  • 我明白你的意思了。打开每个文件并将各自的文件句柄保存到列表中,执行读写,然后关闭列表中的所有句柄?但我想在这种情况下不能使用“with open()”?

标签: python with-statement


【解决方案1】:

在 Python 3.3 及更高版本中,contextlib.ExitStack 可用于正确且良好地执行此操作:

from contextlib import ExitStack

with open('source_dataset.txt') as src_file, ExitStack() as stack:
    files = [stack.enter_context(open(fname, 'w')) for fname in fname_list]
    ... do stuff with src_file and the values in files ...
... src_file and all elements in stack cleaned up on block exit ...

【讨论】:

  • ExitStack 是一个特别好的工具,因为即使在打开后面的文件之一时(在成功打开之前的文件之后)发生异常,它也会表现得很好。大多数天真的解决方案会在这种情况下泄漏打开的文件(直到垃圾收集器清理文件对象)。
  • @Blckknght:是的。我不想深入细节,因为害怕掩盖简单性(文档链接无论如何都涵盖了它),但是,它正确做到这一点并不是一件小事,因为你说。
【解决方案2】:

你可以定义一个类openfiles来支持with语句:

class openfiles:
    def __init__(self, filelist, mode='r'):
        self.fhandles = [open(f, mode) for f in filelist]

    def __enter__(self):
        return self.fhandles

    def __exit__(self, type, value, traceback):
        map(file.close, self.fhandles)

那么你可以:

with openfiles(['file1', 'file2']) as files:
    for f in files:
        print(f.read())

【讨论】:

  • 哇!太优雅了!
  • @LegoStormtroopr:超级优雅,但如果第二个或后续文件 open 失败则完全错误(另外,使用 map 表示 close 是错误的形式,会创建不必要的 lists Nones,甚至不适用于 Py3)。在这种情况下,到目前为止打开的文件都没有确定性地关闭。因为这个模式很容易出错,所以创建了ExitStack。
  • 感谢您提供详细信息。
猜你喜欢
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多