【问题标题】:Treat separate files as one file object in python在python中将单独的文件视为一个文件对象
【发布时间】:2016-06-04 17:53:40
【问题描述】:

我有一个拆分文件(比如说 name.a0、name.a1、name.a2、...)

有没有一种方法可以拥有一个可读的类似文件的对象,将这些对象串联起来,而不使用临时文件并且不将它们全部加载到内存中?

【问题讨论】:

  • 如果底层文件被修改(特别是如果它们改变大小),你打算做什么?例如,如果您在name.a1 中途并且name.a0 变大,对象是否应该自动调整其偏移量以确保您仍然在name.a1 中途?
  • 我不在乎。在我的情况下它们不会改变

标签: python file concatenation


【解决方案1】:

python 标准库中的fileinput 模块正是用于此目的。

import fileinput
with fileinput.input(files=('name.a0', 'name.a1', 'name.a2')) as f:
    for line in f:
        process(line)

【讨论】:

  • Ick,我怎么能忘记fileinput。该模块本质上创建了一个代理,就像我在回答中描述的那样。
  • 看起来不错,但是有一个问题。我的文件是二进制文件而不是文本文件,而且似乎 fileinput 只实现读取行,而不是文件的所有功能
  • 另外,如果这不是你想要的,那么这个问题就是不合格的,并且没有提供足够的信息来给你想要的答案,因为我自己和@MartijnPieters 都回答了这个问题逐行阅读。
【解决方案2】:

您始终可以创建一个代理对象,将一系列文件视为一个文件。您需要实现足够的file object interface 来满足您的程序需求。

例如,如果您所做的只是遍历所有这些文件中的行,那么对于 Python 2,以下对象就足够了:

class MultiFile(object):
    def __init__(self, *filenames, mode='r'):
        self._filenames = reversed(filenames) # reversed iterable
        self._mode = mode
        sef._openfile = open(next(self._filenames), self._mode)

    def __enter__(self):
        return self

    def __exit__(self, *exception_info):
        self._openfile.close()

    __del__ = __exit__

    def __iter__(self):
        return self

    def __next__(self):
        try:
            return next(self._openfile)
        except StopIteration:
            # find next file to yield from, raises StopIteration
            # when self._filenames has run out
            while True:
                self._opefile.close()
                self._openfile = next(self._filenames)
                try:
                    return next(self._openfile, self._mode)
                except StopIteration:
                    continue

这使您可以像阅读一个文件一样阅读 一系列 文件,边读边读(因此永远不会将所有内容都放入内存):

import glob

for line in MultiFile(glob.glob('name.a?')):
    # ...

请注意,在 Python 3 中(或在 Python 2 中使用 io library 时)您需要为文件模式(原始、缓冲或文本)实现适当的 base classes 之一。

【讨论】:

  • 感谢您的回答。我知道我可以自己实现这样的东西,但我一直在寻找一个内置的实现。
  • @BugaleBugalit:如您所见,fileinput 仅处理迭代(连续的file.readline() 调用)。如果您需要使用file.read() 调用读取二进制文件,标准库中没有实现。
猜你喜欢
  • 1970-01-01
  • 2016-02-28
  • 2011-10-07
  • 2019-01-28
  • 1970-01-01
  • 2019-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多