使用缓冲读取器处理大型 .csv 文件,Python

5
我将尝试在Python脚本中打开大型的.csv文件(16k行+,约15列),但是遇到了一些问题。
我使用内置的open()函数打开文件,然后使用输入文件声明csv.DictReader。循环结构如下:
for (i, row) in enumerate(reader):
     # do stuff (send serial packet, read response)

然而,如果我使用超过大约20行的文件,则该文件将打开,但在几次迭代之后,我会收到ValueError:在关闭的文件上进行I/O操作。

我的想法是我可能用尽了内存(尽管16k行文件仅为8MB,我有3GB的RAM),在这种情况下,我希望我需要使用某种缓冲区一次只加载文件的部分到内存中。
我走对了吗?还是文件意外关闭可能有其他原因?
编辑:对于11行的csv,我运行此程序约一半的时间会出现ValueError。错误并不总是发生在同一行。

你是否尝试使用csv.Reader并通过for row in reader: do_stuff()进行迭代,是否遇到了相同的问题?对于这种类型的问题来说,这个文件相对较小。 - jcomeau_ictx
是的,当我只使用for row in reader时,我也遇到了相同的错误。 - Trey
2
你的内存很可能不会用完。其他进程是否正在操作该文件?您是否以正确的模式打开了文件?如果您使用一个20行的文件,是否能得到预期的结果?你在以上评论中提到的“发送串行数据包”是什么意思 -- 是否可能是I/O错误来自于这一步而不是CSV阅读器本身?提供完整的traceback总是很好的。 - Russell Borogove
你的CSV文件很小。错误与大小无关。很可能与CSV文件完全无关。展示你的所有代码。展示完整的回溯信息。 - John Machin
@Russell - 文件上没有运行其他进程。使用20行文件,我没有得到预期的(工作)结果。我的脚本还使用了pySerial模块向嵌入式处理器发送串行数据包,这就是我在注释中所说的。将尽快发布回溯信息... - Trey
你确定CSV文件格式正确吗?如果引号没有匹配,可能会导致你描述的错误。 - user340140
2个回答

4

对于3GB内存来说,16000行代码并不算多,很可能你的问题出在其他方面,比如在某些进程中花费了太多时间,从而干扰了已打开的文件。为确保稳定性和加快速度,建议把整个文件加载到内存中再进行解析。

import csv
import cStringIO
data = open("/tmp/1.csv").read()
reader = csv.DictReader(cStringIO.StringIO(data))
for row in reader:
    print row

至少在这种情况下,您不应该收到文件打开错误。


这成功地打印了16k行文件的全部内容。 - Trey
@Trey,所以它证实了没有像你预期的那样的文件读取问题。 - Anurag Uniyal
我没有收到任何错误信息,程序只是终止了。这个技巧解决了问题。谢谢。 - PhoebeB

-2

csv_reader更快。将整个文件作为块读取。为了避免内存泄漏,最好使用子进程。 from multiprocessing import Process

def child_process(name):
     # Do the Read and Process stuff here.if __name__ == '__main__':
     # Get file object resource.
      .....
     p = Process(target=child_process, args=(resource,))
     p.start()
     p.join()

更多信息请访问以下链接。 http://articlesdictionary.wordpress.com/2013/09/29/read-csv-file-in-python/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接