[英]Python Pandas leaking memory?
我有一个脚本,它不断测量一些数据并定期将其存储在一个文件中。 过去,我以这种方式(伪代码)将数据存储在“手动创建的 CSV”文件中:
with open('data.csv','w') as ofile:
print('var1,var2,var3,...,varN', file=ofile) # Create CSV header.
while measure:
do_something()
print(f'{var1},{var2},{var3},...,{varN}', file=ofile) # Store data.
我以这种方式工作了几个月并运行了这个脚本数百次,除了 1)当 N 很大(在我的情况下在 20 到 30 之间)和 2)CSV 时,这很麻烦(并且容易出错)不保留数据类型。 所以我决定改成这样:
temporary_df = pandas.DataFrame()
while measure:
do_something()
temporary_df.append({'var1':var1,'var2':var2,...,'varN':varN}, ignore_index=True)
if save_data_in_this_iteration():
temporary_df.to_feather(f'file_{datetime.datetime.now()}.fd')
temporary_df = pandas.DataFrame() # Clean the dataframe.
merge_all_feathers_into_single_feather()
乍一看,这和我预期的一样完美。 然而,几个小时后 Python 崩溃了。 在 Windows 和(单独的)Linux 机器 I 中经历过这种情况后,我注意到问题是 Python 正在缓慢地吸取机器的内存,直到没有更多内存,然后当然会崩溃。
由于功能do_something
是不变的两种方法,以及碰撞发生之前merge_all_feathers_into_single_feather
被调用, save_data_in_this_iteration
是平凡简单,我指责大熊猫这个问题。
谷歌告诉我,过去其他人在使用 Pandas 时遇到过记忆问题。 我已经尝试在每次迭代中添加垃圾收集器行,如建议例如此处,但对我不起作用。 我还没有尝试多处理方法,因为它看起来像用核武器杀死一只蚂蚁,并且可能会带来其他并发症......
有没有什么解决方案可以像这样继续使用 Pandas? 不使用 Pandas 有没有更好的解决方案? 哪一个?
在解决这个问题一段时间后,我决定创建一个 MWE 来做一些测试。 所以我写了这个:
import pandas
import numpy
import datetime
df = pandas.DataFrame()
while True:
df = df.append({f'col_{i}': numpy.random.rand() for i in range(99)}, ignore_index=True)
if 'last_clean' not in locals() or (datetime.datetime.now()-last_clean).seconds > .5:
last_clean = datetime.datetime.now()
df.to_feather('delete_me.fd')
df = df[0:0]
令我惊讶的是,这个脚本并没有耗尽内存! 所以在这里我得出结论,Pandas 不是我的问题。
然后我向 MWE 添加了一个新组件,我发现了问题:
import pandas
import numpy
import datetime
import matplotlib.pyplot as plt
def save_matplotlib_plot(df):
fig, ax = plt.subplots()
ax.plot(df['col_1'], df['col_2'])
fig.savefig('delete_me.png')
# Uncomment the following two lines to release the memory and stop the "leak".
# ~ fig.clear()
# ~ plt.close(fig)
df = pandas.DataFrame()
while True:
df = df.append({f'col_{i}': numpy.random.rand() for i in range(99)}, ignore_index=True)
if 'last_clean' not in locals() or (datetime.datetime.now()-last_clean).seconds > .5:
last_clean = datetime.datetime.now()
df.to_feather('delete_me.fd')
save_matplotlib_plot(df) # Here I had my "leak" (which was not a leak indeed because matplotlib keeps track of all the figures it creates, so it was working as expected).
df = df[0:0]
似乎当我从“手工制作的 CSV”切换到“Pandas”时,我也对情节进行了一些更改,因此当它不是问题时,我将其归咎于 Pandas。
只是为了完整性,多处理解决方案也有效。 以下脚本没有内存问题:
import pandas
import numpy
import datetime
import matplotlib.pyplot as plt
from multiprocessing import Process
def save_matplotlib_plot(df):
fig, ax = plt.subplots()
ax.plot(df['col_1'], df['col_2'])
fig.savefig('delete_me.png')
df = pandas.DataFrame()
while True:
df = df.append({f'col_{i}': numpy.random.rand() for i in range(99)}, ignore_index=True)
if 'last_clean' not in locals() or (datetime.datetime.now()-last_clean).seconds > .5:
last_clean = datetime.datetime.now()
df.to_feather('delete_me.fd')
p = Process(target=save_matplotlib_plot, args=(df,))
p.start()
p.join()
df = df[0:0]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.