如何使用Python的csv模块有效地将字典输出为csv文件?内存不足错误

时间:2010-07-14 20:33:02

标签: python csv dictionary

我正在尝试使用Python的CSV模块将字典列表序列化为csv文本文件。我的列表有大约13,000个元素,每个元素都是一个包含〜100个键的字典,由简单的文本和数字组成。我的函数“dictlist2file”只是调用DictWriter来序列化它,但是我的内存错误。

我的功能是:

def dictlist2file(dictrows, filename, fieldnames, delimiter='\t',
                  lineterminator='\n', extrasaction='ignore'):
    out_f = open(filename, 'w')

    # Write out header
    if fieldnames != None:
        header = delimiter.join(fieldnames) + lineterminator
    else:
        header = dictrows[0].keys()
        header.sort()
    out_f.write(header)

    print "dictlist2file: serializing %d entries to %s" \
          %(len(dictrows), filename)
    t1 = time.time()
    # Write out dictionary
    data = csv.DictWriter(out_f, fieldnames,
              delimiter=delimiter,
              lineterminator=lineterminator,
                          extrasaction=extrasaction) 
    data.writerows(dictrows)
    out_f.close()
    t2 = time.time()
    print "dictlist2file: took %.2f seconds" %(t2 - t1)

当我在字典上尝试这个时,我得到以下输出:

dictlist2file: serializing 13537 entries to myoutput_file.txt
Python(6310) malloc: *** mmap(size=45862912) failed (error code=12)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
Traceback (most recent call last):
...
  File "/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/csv.py", line 149, in writerows
    rows.append(self._dict_to_list(rowdict))
  File "/Library/Frameworks/Python.framework/Versions/6.2/lib/python2.6/csv.py", line 141, in _dict_to_list
    return [rowdict.get(key, self.restval) for key in self.fieldnames]
MemoryError

知道可能导致这种情况的原因是什么?该列表只有13,000个元素,字典本身非常简单和小(100个键),所以我不明白为什么这会导致内存错误或效率低下。它需要几分钟才能得到内存错误。

感谢您的帮助。

4 个答案:

答案 0 :(得分:3)

DictWriter.writerows(...)获取您传递给它的所有dicts并创建(在内存中)一个新的列表列表,每行一个。因此,如果您有大量数据,我可以看到如何弹出MemoryError。您可以采取两种方式:

  1. 自己对列表进行迭代,并为每个列表调用DictWriter.writerow一次。虽然这意味着很多写作。
  2. 将行批处理到较小的列表,并为它们调用DictWriter.writerows。减少IO,但是你可以避免分配大量的内存。

答案 1 :(得分:1)

你可能会绊倒内部Python问题。我会在bugs.python.org上报告。

答案 2 :(得分:0)

我对csv的情况没有答案,但我发现以下替代品在不到几秒的时间内将字典序列化为一个文件:

for row in dictrows:
    out_f.write("%s%s" %(delimiter.join([row[name] for name in fieldnames]),
                         lineterminator))

其中dictrows是由dictReader从csv生成的字典生成器,fieldnames是一个字段列表。

任何有关为什么csv表现不同的想法都将非常感激。感谢。

答案 3 :(得分:0)

你说如果你遍历data.writerow(single_dict)它仍然会遇到问题。输入代码以显示每100行的行数。在获得内存错误之前处理了多少个dicts?运行更多或更少的进程以吸收更多或更少的内存...失败的地方会变化吗?

什么是max(len(d) for d in dictrows)?字符串中的字符串有多长?

你有多少可用内存?

更新:查看Dictwriter是否存在问题;消除它并使用基本的csv功能:

writer = csv.writer(.....)
for d in dictrows:
   row = [d[fieldname] for fieldname in fieldnames]
   writer.writerow(row)