【问题标题】:Python: efficient file ioPython:高效的文件 io
【发布时间】:2011-11-08 03:56:19
【问题描述】:

同时读取两个大文件并进行一些处理的最有效(最快)方法是什么?

我有两个文件; a.txt 和 b.txt,每个都包含大约十万行。我的目标是读入这两个文件,然后对每一行对进行一些处理

def kernel:
    a_file=open('a.txt','r')
    b_file=open('b.txt', 'r')
    a_line = a_file.readline()
    b_line = b_file.readline()
    while a_line:
        process(a_spl,b_spl) #process requiring both corresponding file lines

我查看了 xreadlines 和 readlines,但我想知道我是否可以做得更好。速度对于这项任务至关重要。

谢谢。

【问题讨论】:

  • Python 的速度不是很好。推荐使用 C 或 C++。试试看:stackoverflow.com/questions/5164538/…
  • @Alvin K.:配置文件优先:Python 仍然足够快,能够超过 大多数 形式的 I/O,尤其是如果所述 I/O 正在访问磁盘或网络。
  • @Thanatos:上面的链接中也提到了分析,它声称 I/O 不是主要瓶颈。感谢您强调它。

标签: python file-io


【解决方案1】:

以下代码不会从内存中的输入文件累积数据,除非process 函数自己这样做。

from itertools import izip

def process(line1, line2):
  # process a line from each input

with open(file1, 'r') as f1:
  with open(file2, 'r') as f2:
    for a, b in izip(f1, f2):
      process(a, b)

如果process 函数高效,则此代码对于大多数用途来说应该足够快。当到达一个文件的末尾时,for 循环将终止。如果任一文件包含非常长的行(即 XML、JSON),或者文件不是文本,则此代码可能无法正常工作。

【讨论】:

  • 您忘记提及您的文件需要itertools 模块。没有以下内容将无法工作:from itertools import izip.
  • 那么如果你不给它一个句柄,你怎么能明确地关闭它呢?
  • 已编辑以解决上述两个 cmets。
【解决方案2】:

您可以使用with 语句来确保您的文件在执行后关闭。来自this blog entry

要打开文件、处理其内容并确保将其关闭,您只需执行以下操作:

with open("x.txt") as f:
    data = f.read()
    do something with data

【讨论】:

    【解决方案3】:

    字符串 IO 可以非常快 - 可能您的处理会减慢速度。考虑一个简单的输入循环来提供队列,例如:

    queue = multiprocessing.Queue(100)
    a_file = open('a.txt')
    b_file = open('b.txt')
    for pair in itertools.izip(a_file, b_file):
         queue.put(pair) # blocks here on full queue
    

    假设您的问题可以通过这种方式并行化,您可以设置一个进程池,从队列中提取项目并对每个项目采取行动。

    【讨论】:

    • 在 Python 2.x 中,请务必使用 itertools.izip(),这样 zip 步骤就不会同时发生,并将两个文件完全拉入内存。
    • 也许是这样,我在每一步都读取令牌列表并将其存储在列表中。也许这就是瓶颈。程序正在占用内存。
    • 感谢 Raymond 发现了这个明显的错误。在这种情况下绝对使用 izip,而不是 zip。我已经修复了这个例子。
    • 感谢您的建议。使用 izip 让它工作。也解决了我的记忆问题。对算法做了一些优化,减少了空间消耗。
    【解决方案4】:

    我会将您的 while 条件更改为以下内容,以便当 a 的行数多于 b 时它不会失败。

    while a_line and b_line
    

    否则,这看起来不错。您正在阅读您需要的两行,然后进行处理。您甚至可以通过读入N 行对并将每对行发送到新线程或类似线程来实现多线程。

    【讨论】:

    • 我们确信它将是同一行。目标是减少 r.t.所以避免了额外的检查
    • 您的程序会在您最意想不到的时候严重崩溃。如果您有充分的理由担心周期,请切换到 C。
    • zip 将停在两个文件中较短的那个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 2021-01-22
    相关资源
    最近更新 更多