仅创建1个matplotlib图却触发20个已打开RuntimeWarning如何解决
问题排查与解决方案
原因排查
- 首先要明确:你所说的"代码仅会运行一次"是单次请求内的执行逻辑,实际每次前端请求该图片接口都会触发一次绘图操作,多次请求累计创建的画布数量达到20就会触发告警
- Flask默认启用多线程处理请求,并发场景下多个请求同时创建画布时,matplotlib的全局状态可能出现冲突,部分请求的
plt.close(fig)没有正确生效 - 若绘图过程中出现异常,逻辑会直接跳出,不会执行到末尾的
plt.close(fig),导致该画布一直驻留在内存中 - matplotlib默认使用交互式后端,会额外持有画布的GUI引用,即使显式调用close也可能出现内存未完全释放的问题
可落地解决方案
- 强制使用非交互式后端,专门适配生成图片的场景,避免GUI相关的内存持有,注意该配置必须放在导入
matplotlib.pyplot之前:
import matplotlib matplotlib.use('Agg') # 非交互后端,无GUI渲染,仅生成图片文件 import matplotlib.pyplot as plt
- 用上下文管理器包裹绘图逻辑,保证不管逻辑是否抛出异常,都能自动关闭画布释放资源,不需要手动调用
plt.close:
with plt.subplots() as (fig, ax): plt.imshow(plot_data, extent=[0, max_distance, y_lims[0], y_lims[1]],cmap=cmap, origin='lower', norm=Normalize(-20, 75),aspect=300) ax.yaxis_date() ax.yaxis.set_major_formatter(yfmt) ax.yaxis.set_major_locator( mdates.HourLocator(interval = 1)) plt.grid(b=True, which='major', color='#666666', linestyle='-') figdata = BytesIO() fig.tight_layout() fig.savefig(figdata, format='png') # 退出with块自动释放画布资源 resp = Response(figdata.getvalue(), mimetype='image/png')
- 若服务并发量确实很高,可按需调高告警阈值(优先做资源释放优化,该方案仅作为补充):
plt.rcParams.update({'figure.max_open_warning': 50})
- 如果是多worker部署的Flask服务,给每个worker单独配置matplotlib实例,避免跨进程的资源冲突。
内容的提问来源于stack exchange,提问作者eng3
相关产品推荐
相关产品推荐

