如何在不崩溃的情况下处理 python 中的超大文件 (13GB)?
How do I process very large file (13GB) in python without crashing?
我必须在服务器(不是我的电脑)上处理这个非常大的文件。它运行 python 64 并具有 24 GB 的 RAM。该文件本身的大小约为 13GB,包含 2700 万行数据。考虑到服务器有相当大的规格,我确实尝试将整个加载到 pandas,但它崩溃了。我尝试使用 dask,但它仍然很慢。所以我将文件分成如下块。
我的代码与下面类似。我以块的形式加载文件,每个块是 100,000 行数据。然后它将处理每个块,并将其附加到现有文件。我认为通过分块处理事物,它不会将数据存储在 RAM 中,但我认为它仍然存在。前几百次迭代工作正常,但在处理 8GB 数据后的某个时候,它就崩溃了。
chunksize= 100000
c = 0
for chunk in pd.read_csv(fname, chunksize=chunksize,sep='|',error_bad_lines=False):
chunk['col1'] = chunk['col1'].apply(process1)
chunk['col2'] = chunk['col2'].apply(process2)
if c == 0:
chunk.to_csv("result/result.csv", index=False)
else:
chunk.to_csv('result/result.csv', mode='a', header=False, index=False)
if c%10==0:
print(c)
c+=1
通常在产生 8 GB 的 result.csv 文件的 160 次迭代之后,程序会以 MemoryError:
.
停止
老实说,我无权访问此服务器中的许多内容,因此如果您想建议更改一些我无权访问的设置,那么我可能做不到。但是让我们看看我能做什么。提前致谢。
编辑:
我将在这里添加 process1
和 process2
中发生的事情。
def process1(name):
if type(name)==str:
new_name = name[:3]+'*' * len(name[:-3])
else:
return name
return new_name
def process2(number):
if number !=np.nan:
new_number = str(number)
new_number = '*'*len(new_number)
return new_number
else:
return number
for
循环的一般语法是
for target in expression:
do all the things
Python 会将表达式计算为一个对象,只有在计算完成后,它才会将该对象分配给目标变量。这意味着任何已经在 target
中的对象在其替换被构建之前不会被删除。
这没什么大不了的,除非创建的对象很大。这里就是这种情况。 about-to-be 删除的块在创建新块时在内存中,有效地加倍了对内存的影响。解决方法是在循环中手动删除target,然后返回for more。
for chunk in pd.read_csv(fname, chunksize=chunksize,sep='|',error_bad_lines=False):
chunk['col1'] = chunk['col1'].apply(process1)
chunk['col2'] = chunk['col2'].apply(process2)
if c == 0:
chunk.to_csv("result/result.csv", index=False)
else:
chunk.to_csv('result/result.csv', mode='a', header=False, index=False)
del chunk # destroy dataframe before next loop to conserve memory.
if c%10==0:
print(c)
c+=1
我必须在服务器(不是我的电脑)上处理这个非常大的文件。它运行 python 64 并具有 24 GB 的 RAM。该文件本身的大小约为 13GB,包含 2700 万行数据。考虑到服务器有相当大的规格,我确实尝试将整个加载到 pandas,但它崩溃了。我尝试使用 dask,但它仍然很慢。所以我将文件分成如下块。
我的代码与下面类似。我以块的形式加载文件,每个块是 100,000 行数据。然后它将处理每个块,并将其附加到现有文件。我认为通过分块处理事物,它不会将数据存储在 RAM 中,但我认为它仍然存在。前几百次迭代工作正常,但在处理 8GB 数据后的某个时候,它就崩溃了。
chunksize= 100000
c = 0
for chunk in pd.read_csv(fname, chunksize=chunksize,sep='|',error_bad_lines=False):
chunk['col1'] = chunk['col1'].apply(process1)
chunk['col2'] = chunk['col2'].apply(process2)
if c == 0:
chunk.to_csv("result/result.csv", index=False)
else:
chunk.to_csv('result/result.csv', mode='a', header=False, index=False)
if c%10==0:
print(c)
c+=1
通常在产生 8 GB 的 result.csv 文件的 160 次迭代之后,程序会以 MemoryError:
.
老实说,我无权访问此服务器中的许多内容,因此如果您想建议更改一些我无权访问的设置,那么我可能做不到。但是让我们看看我能做什么。提前致谢。
编辑:
我将在这里添加 process1
和 process2
中发生的事情。
def process1(name):
if type(name)==str:
new_name = name[:3]+'*' * len(name[:-3])
else:
return name
return new_name
def process2(number):
if number !=np.nan:
new_number = str(number)
new_number = '*'*len(new_number)
return new_number
else:
return number
for
循环的一般语法是
for target in expression:
do all the things
Python 会将表达式计算为一个对象,只有在计算完成后,它才会将该对象分配给目标变量。这意味着任何已经在 target
中的对象在其替换被构建之前不会被删除。
这没什么大不了的,除非创建的对象很大。这里就是这种情况。 about-to-be 删除的块在创建新块时在内存中,有效地加倍了对内存的影响。解决方法是在循环中手动删除target,然后返回for more。
for chunk in pd.read_csv(fname, chunksize=chunksize,sep='|',error_bad_lines=False):
chunk['col1'] = chunk['col1'].apply(process1)
chunk['col2'] = chunk['col2'].apply(process2)
if c == 0:
chunk.to_csv("result/result.csv", index=False)
else:
chunk.to_csv('result/result.csv', mode='a', header=False, index=False)
del chunk # destroy dataframe before next loop to conserve memory.
if c%10==0:
print(c)
c+=1