我通过使用pandas read_csv 以及500000的块大小并写入另一个csv文件来丰富一个拥有7.5亿行的csv。运行此操作后,我处理了大约1亿到1亿5千万行后,会出现'分段错误' 。
我跟踪处理的块数并更改了代码,因此它会跳过它已读取的块。监视进程内存消耗我发现即使我跳过这些块,它也会增加很多。这是我不能得到的部分。通过问题似乎是熊猫垃圾收集的问题,但这似乎与以前的版本有关。我使用Python 2.7 和pandas 0.21.0
我在具有30 GB RAM的r3.xlarge EC2实例上执行此操作,这应该足够了,即使考虑到高达6倍内存开销的pandas。
代码摘要:
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是一个相对较小的表,保存在内存中。
答案 0 :(得分:0)
我编写了一个简化的测试脚本,无法重现您的错误。我使用的是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))