如何使用Python的csv模块高效导出字典为csv文件?内存溢出错误

4 投票
4 回答
7162 浏览
提问于 2025-04-16 01:18

我正在尝试使用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 个回答

1

你可能遇到了Python内部的问题。建议你去bugs.python.org上报告一下。

3

DictWriter.writerows(...) 这个方法会把你传给它的所有字典都拿来,创建一个新的列表,每一行对应一个列表。所以如果你的数据量很大,就可能会出现 MemoryError 的错误。你可以考虑以下两种方法:

  1. 自己遍历这个列表,然后对每一个字典调用一次 DictWriter.writerow。不过这样会导致很多次写入。
  2. 把行分成小的列表,然后对这些小列表调用 DictWriter.writerows。这样写入次数会少一些,但可以避免一次性占用太多内存。
0

我不知道csv到底发生了什么,但我发现下面这个替代方法可以在几秒钟内把字典保存到文件里:

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

这里的dictrows是通过csv中的DictReader生成的字典生成器,fieldnames是一个字段名称的列表。

如果有人知道为什么csv的表现不一样,那就太好了,谢谢!

撰写回答