【问题标题】:Pandas read_csv with chunksize memory leak带有块大小内存泄漏的 Pandas read_csv
【发布时间】:2017-11-01 10:56:09
【问题描述】:

我正在通过使用块大小为 500000 的 pandas read_csv 并写入另一个 csv 文件来丰富 7.5 亿行的 csv。在处理大约 100 到 1.5 亿行后,运行这个我得到一个 'segmentation fault'

我记录了已处理的块数并更改了代码,因此它会跳过它已读取的块。监控进程内存消耗我发现它增加了很多,即使我跳过了块。那是我不明白的部分。通过这些问题,熊猫垃圾收集似乎存在问题,但这似乎与以前的版本有关。我正在使用 Python 2.7 和 pandas 0.21.0

我在具有 30 GB RAM 的 r3.xlarge EC2 实例上执行此操作,这应该足够了,即使考虑到 pandas 高达 6 倍的内存开销。

代码摘要:

i = 0
for chunk in pd.read_csv(filename,chunksize=500000,names=colnames):
    if  i <= 349500000: # Previously processed chunks
        i = i+chunksize
        print 'Skipping chunk ', i
        continue
    enriched_chunk = enrich_df(chunk, users_df)
    enriched_chunk.to_csv('enriched.csv', mode='a', header=False, index=False)


def enrich_df(c, users_df):
    d = pd.merge(c, users_df, how='left', left_on='user_id', right_on='userId')
    return d

users_df 表是一个相对较小的表,保存在内存中。

【问题讨论】:

    标签: python pandas csv


    【解决方案1】:

    我编写了一个简化的测试脚本,无法重现您的错误。我正在使用 Python 3.6.1 和 Pandas 0.20.3。

    测试脚本使用恒定的 306 MB RAM(至少对于前 1 亿行,它仍在运行)。

    你可以试试这个脚本,看看它是否仍然会产生内存泄漏?它可以作为调试的起点。

    import os
    import time
    
    import numpy as np
    import pandas as pd
    import matplotlib.pylab as plt
    
    SOURCE = 'test.csv'
    CHUNCKSIZE = int(5e5)
    
    def main():
    
        if not os.path.exists(SOURCE):
            df = pd.DataFrame(np.random.rand(1000000, 4), columns=list('ABCD'))
            df.to_csv(SOURCE)
            del df
        print("df %s ready" %(SOURCE))
    
        i=0; lines=[]; timings = []
        while(i < int(7e8)): 
            t = time.time()
            print(i, end = ' ')
            i += CHUNCKSIZE
            chunk = pd.read_csv(SOURCE, chunksize=CHUNCKSIZE)
            chunk = pd.concat(chunk, ignore_index=True)
            chunk.to_csv('enriched.csv', mode='a', header=False, index=False)
            print(" in %.3f seconds" %(time.time() -t))
            lines.append(i)
            timings.append(time.time()-t)
    
    
        plt.figure(figsize=(10,5))
        plt.plot(lines, timings, 'o-')
        plt.xlabel("Nr of lines"); plt.ylabel("Time for last chunck")
        plt.show()
    
    
    
    
    if __name__ == "__main__":
        st = time.time()
        main()
        print("--- total runtime %.3f seconds ---" %(time.time() - st))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-15
      • 1970-01-01
      • 2010-11-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多