You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Matplotlib调用函数后未释放RAM内存的问题排查求助

内存泄漏原因分析及解决办法

核心原因

从你的内存分析数据能看出关键问题:

  • plt.show()执行后内存暴涨到487MiB,但plt.close('all')没有释放任何内存,说明matplotlib的绘图资源(尤其是窗口相关的)没被彻底清理。
  • 最终调用gc.collect()后内存仍高于初始值,说明存在循环引用或底层后端资源未释放,导致垃圾回收器无法彻底回收内存。

具体拆解:

  1. matplotlib交互式后端的资源残留
    plt.show()会启动交互式后端(比如TkAgg、QtAgg)创建窗口,这些窗口的底层句柄、渲染缓存等资源,仅靠plt.close('all')可能无法完全销毁。递归调用时,这些未释放的资源会不断累积,最终耗尽内存。

  2. 超高dpi导致的巨量像素数据残留
    你设置的dpi=10000完全不合理——哪怕是10x10英寸的图,像素量会达到100000×100000,生成的像素数组会占用数GB内存。即使关闭figure,这些巨量数据的引用可能被matplotlib的全局缓存或后端残留持有,无法被GC回收。

  3. 递归调用的全局状态污染
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 08:25:19