如何在不崩溃的情况下处理 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:.

停止

老实说,我无权访问此服务器中的许多内容,因此如果您想建议更改一些我无权访问的设置,那么我可能做不到。但是让我们看看我能做什么。提前致谢。

编辑: 我将在这里添加 process1process2 中发生的事情。

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