我正在尝试找出读取/处理超大文件行的最佳方法。 我在这里试试
for line in f:
我的部分脚本如下:
o=gzip.open(file2,'w')
LIST=[]
f=gzip.open(file1,'r'):
for i,line in enumerate(f):
if i%4!=3:
LIST.append(line)
else:
LIST.append(line)
b1=[ord(x) for x in line]
ave1=(sum(b1)-10)/float(len(line)-1)
if (ave1 < 84):
del LIST[-4:]
output1=o.writelines(LIST)
我的file1
大约是10GB;当我运行脚本时,内存使用量不断增加到15GB而没有任何输出。这意味着计算机仍然首先尝试将整个文件读入内存,对吧?这与使用readlines()
然而在帖子中:
Different ways to read large data in python
斯里卡告诉我:
The for line in f
将文件对象f视为可迭代的,它会自动使用缓冲的IO和内存管理,因此您不必担心大文件。
但显然我仍然需要担心大文件......我真的很困惑。 THX
编辑: 在我的数据中,每4行都是一种组。 目的是每4行进行一些计算;并根据该计算,决定是否需要追加这4行。所以写作是我的目的。
答案 0 :(得分:4)
内存保持原因的原因。即使您使用enumerator
之后,也因为您使用的是LIST.append(line)
。这基本上累积了列表中文件的所有行。显然它全都坐在记忆中。你需要找到一种不累积这样的线的方法。阅读,处理和继续下一步。
你可以做的另一种方法是以块的形式读取你的文件(事实上,一次读取1行可以符合这个标准,1chunk == 1line),即读取文件进程的一小部分,然后读取下一个块我仍然认为这是在python中读取大小文件的最佳方法。
with open(...) as f:
for line in f:
<do something with line>
with
语句处理打开和关闭文件,包括是否在内部块中引发异常。 for line in f
将文件对象f
视为可迭代,它自动使用缓冲的IO和内存管理,因此您不必担心大文件。
答案 1 :(得分:1)
看起来在这个函数的最后,你将你读过的所有行都读入内存,然后立即将它们写入文件。也许你可以尝试这个过程:
我没试过这个,但它可能看起来像这样:
o=gzip.open(file2,'w')
f=gzip.open(file1,'r'):
LIST=[]
for i,line in enumerate(f):
if i % 4 != 3:
LIST.append(line)
else:
LIST.append(line)
b1 = [ord(x) for x in line]
ave1 = (sum(b1) - 10) / float(len(line) - 1
# If we've found what we want, save them to the file
if (ave1 >= 84):
o.writelines(LIST)
# Release the values in the list by starting a clean list to work with
LIST = []
编辑:尽管如此,由于您的文件太大,这可能不是最好的技术,因为您必须写入文件的所有行,但无论如何都值得调查。
答案 2 :(得分:0)
由于您将所有行添加到列表LIST
中,并且有时只从其中删除一些行,LIST
我们会变得越来越长。您存储在LIST
中的所有行都将占用内存。如果您不希望它们占用内存,请不要将所有行保留在列表中。
此外,您的脚本似乎没有在任何地方产生任何输出,所以重点是不是很清楚。
答案 3 :(得分:0)
好的,你知道其他评论/答案中你的问题是什么,但让我简单说明一下。
您只是一次只读一行内存,但是您通过附加到列表中将其中很大一部分存储在内存中。
为了避免这种情况,你需要在文件系统或数据库(在磁盘上)存储一些东西,以便以后查看你的算法是否足够复杂。
从我看来,你似乎可以轻松地逐步写出输出。即。 您当前正在使用列表存储有效行以写入输出以及您可能在某些时候删除的临时行。为了提高内存效率,只要知道这些行是有效输出,就要从临时列表中写出行。
总之,使用您的列表只存储您根据需要进行计算所需的临时数据,一旦您准备好输出有效数据,您就可以将其写入磁盘并从主存储器中删除(在python这意味着你不应再对它有任何引用。)
答案 4 :(得分:0)
如果您不使用with
语句,则必须关闭文件的处理程序:
o.close()
f.close()