Matplotlib调用函数后未释放RAM内存的问题排查求助
核心原因
从你的内存分析数据能看出关键问题:
plt.show()执行后内存暴涨到487MiB,但plt.close('all')没有释放任何内存,说明matplotlib的绘图资源(尤其是窗口相关的)没被彻底清理。- 最终调用
gc.collect()后内存仍高于初始值,说明存在循环引用或底层后端资源未释放,导致垃圾回收器无法彻底回收内存。
具体拆解:
matplotlib交互式后端的资源残留
plt.show()会启动交互式后端(比如TkAgg、QtAgg)创建窗口,这些窗口的底层句柄、渲染缓存等资源,仅靠plt.close('all')可能无法完全销毁。递归调用时,这些未释放的资源会不断累积,最终耗尽内存。超高dpi导致的巨量像素数据残留
你设置的dpi=10000完全不合理——哪怕是10x10英寸的图,像素量会达到100000×100000,生成的像素数组会占用数GB内存。即使关闭figure,这些巨量数据的引用可能被matplotlib的全局缓存或后端残留持有,无法被GC回收。递归调用的全局状态污染
matplotlib依赖全局状态机管理figure和axes,递归调用时,每次函数调用的栈帧可能会保留对全局状态的引用,导致旧的figure对象无法被正确销毁。
解决措施
改用非交互式后端,避免窗口资源
在导入pyplot前设置Agg后端,直接保存图片而非显示:import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt用
plt.savefig('output.png')替代plt.show(),彻底避免窗口相关的内存泄漏。降低dpi到合理范围
打印级别的dpi设为300即可,过高的dpi只会徒增内存占用,对实际输出没有意义。使用面向对象API,显式控制资源生命周期
放弃pyplot的全局状态,改用fig, ax = plt.subplots()的方式,每次绘图后显式关闭并删除figure:def my_func(): a = [1] * (10 ** 6) b = [2] * (2 * 10 ** 7) c = a + b fig, ax = plt.subplots(dpi=300) ax.plot(np.random.rand(1000), np.random.rand(1000)) fig.savefig('plot.png') # 显式清理 plt.close(fig) del a, b, c, fig, ax gc.collect()替换递归为循环
递归调用的栈帧会保留引用,改用循环可以避免这种隐式的内存残留,更便于控制每次迭代的资源清理。
内容的提问来源于stack exchange,提问作者Escanyapobres

