【问题标题】:Memory Error When Parsing Large File - Python解析大文件时出现内存错误 - Python
【发布时间】:2012-11-09 10:30:12
【问题描述】:

有人问过关于 Python 中的内存错误的问题,但我想问一个更具体的问题。我是编程和 Python 新手。

解析大文本文件(~8GB)时,行

mylist = [line.strip('\n').split('|') for line in f]

导致“内存错误”。

我在具有 12GB RAM 的 Windows XP 64 位上运行 64 位 Python [MSC v.1500 64 位 (AMD64)]。除了安装更多 RAM 之外,我该如何处理此内存错误?

【问题讨论】:

    标签: python list memory


    【解决方案1】:

    内存错误即将到来,因为您试图将整个文件存储在一个列表中(在内存中)。因此,尝试在每一行上工作而不是存储它:

    for line in f:
       data = line.strip('\n').split('|')
       #do something here with data
    

    【讨论】:

      【解决方案2】:

      这取决于你想用你的列表做什么。

      如果您想逐行工作,您可能可以使用列表生成器而不是列表推导来完成工作,如下所示:

      myiterator = (line.strip('\n').split('|') for line in f)
      

      (不是我将[...] 更改为(...))。这将返回一个迭代器而不是一个列表,并且由于 for line in f 也不会创建一个列表,因此您将一次加载一行。

      如果您想同时处理所有行,您可能必须将其与另一种技术结合使用,以免占用您的所有内存。

      【讨论】:

      • @user1839897 请注意,创建列表生成器实际上并不执行括号内的代码。在您循环生成器之前不会发生这种情况,例如使用for 循环:for line_parts in myiterator:
      • 没错,这也是为什么创建这样的生成器非常便宜的原因,因为计算仅在您真正需要它时发生。此外,它允许您将计算作为生成器值的一部分进行,因此很容易将其他计算组合在一起,作为单个值(生成器)的一部分。它仍然可以看作是一个列表,虽然有一些区别(没有 len()、没有切片、没有索引等)
      【解决方案3】:

      肯定应该使用懒惰的生成器一次解析这样一个巨大的文件,或者将文件划分为较小的块。

      一种可能性:

      def lazy_reader(path):
          """reads a file one line at a time."""
          try:
              file = open(path, 'r')
              while True:
                  line = file.readline()
                  if not line: break
                  yield line             # "outputs" the line from the generator
          except IOError:
              sys.stderr.write("error while opening file at %s\n" % path)
              sys.exit(2)
          finally:
              file.close()
      

      然后,您可以像这样消耗你的发电机,如

      for line in lazy_reader("path/to/your/file"):
          do_something_with(line)
      

      编辑:您还可以以整洁的“流水线”方式组合发电机:

      def parse(generator):
          for line in generator: yield line.strip('\n').split('|')
      
      for data in parse( lazy_reader("path/to/your/file") ):
          do_something_with_splitted_array(data)
      

      【讨论】:

      • @ l4mpi是的,但是读取它包含[line for line in f] not span>的列表
      • 问题中的列表理解可以通过Swapping () span>交换[]
      • @ katrielalex当然不是,但为什么写这个lazy_reader函数然后,如果一个人只能使用内置文件迭代器,它是相同的? span>
      • Ashwini Chaudhary的答案在2行中做了相同的相同,而不是......数十个?我也更简洁,有效。这不是很好的(根本)。 span>
      • 我实际上没有新的()成语。分享的THX。我从一些代码调整了这个答案,我在那里我必须使用数字二进制数据进行解析,其中有这个函数有意义。 span>
      【解决方案4】:

      我的看法是使用with 使错误更容易,生成器来定义lines 的外观,然后对其进行迭代:

      with open('somefile') as fin:
          lines = (line.strip('\n').split('|') for line in fin)
          for line in lines:
              pass # do something with line
      

      【讨论】:

        猜你喜欢
        • 2013-06-19
        • 1970-01-01
        • 2016-08-19
        • 2020-11-19
        • 1970-01-01
        • 2018-10-13
        • 1970-01-01
        • 2021-04-23
        • 2018-03-29
        相关资源
        最近更新 更多