尝试读取大型(~13GB)csv文件时,Python readline()失败

时间:2014-01-03 02:39:11

标签: python python-2.7 csv

我是一个Python新手,在阅读大文本文件时有一个关于内存使用的快速问题。我有一个~13GB的csv我试图逐行阅读Python documentation和更有经验的Python用户建议不要使用 readlines()以避免加载整个归档到内存中。

当尝试从文件中读取一行时,我得到以下错误,并且不确定可能导致它的原因。除了这个错误,我还注意到我的PC的内存使用率过高。这有点令人惊讶,因为我对 readline 函数的理解是它一次只将一行从文件加载到内存中。

作为参考,我使用Continuum Analytic的Anaconda分发的Python 2.7和PyScripter作为我的IDE进行调试和测试。任何帮助或见解都表示赞赏。

with open(R'C:\temp\datasets\a13GBfile.csv','r') as f:
        foo = f.readline(); #<-- Err: SystemError: ..\Objects\stringobject.c:3902 bad argument to internal function

更新:

感谢大家提供快速,翔实且非常有用的反馈,我查看了引用的链接,这正是我遇到的问题。在应用记录的'rU'选项模式后,我能够像正常一样从文件中读取行。我没有注意到我最初引用的文档链接中提到的这种模式,而忽略了首先查看打开函数的详细信息。再次感谢。

1 个答案:

答案 0 :(得分:4)

Unix文本文件以\n结束每一行。

Windows文本文件以\r\n结束每一行。

当您以文本模式'r'打开文件时,Python假定它具有您平台的本机行结尾。

因此,如果您在Windows上打开Unix文本文件,Python将查找\r\n个序列来分割行。但是没有任何东西,所以它会把你的整个文件视为一个巨大的130亿字符行。因此,readline()调用最终会尝试将整个内容读入内存。

对此的修复是使用universal newlines模式,方法是以模式rU打开文件。正如open的文档中所述:

  

提供'U'将文件作为文本文件打开,但行可以通过以下任何一种方式终止:Unix行尾约定'\ n',Macintosh约定'\ r'或Windows惯例'\ r \ n'。

因此,它不是搜索\r\n个序列来分割行,而是查找\r\n\n\r。有数百万\n。所以,问题就解决了。


解决此问题的另一种方法是使用二进制模式'rb'。在这种模式下,Python根本不进行任何转换,并假设所有行都以\n结尾,无论您使用的是什么平台。

就其本身而言,这很糟糕 - 这意味着你最终会在Windows文本文件的每一行末尾增加\r

但这意味着您可以将文件传递给更高级别的文件阅读器,例如需要二进制文件的csv,因此它可以按照自己的方式解析它们。除了神奇地为您解决这个问题之外,更高级别的库也可能使代码的其余部分更简单,更健壮。例如,它可能看起来像这样:

with open(R'C:\temp\datasets\a13GBfile.csv','rb') as f:
    for row in csv.reader(f):
        # do stuff

现在每行都会自动在逗号上拆分,但引号内的逗号或以适当方式转义的逗号不计算,依此类推,因此您需要处理的只是list列值。