我是一个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'选项模式后,我能够像正常一样从文件中读取行。我没有注意到我最初引用的文档链接中提到的这种模式,而忽略了首先查看打开函数的详细信息。再次感谢。
答案 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
列值。