Django Web应用中Matplotlib多请求绘图重叠问题求助
解决Django中Matplotlib多请求图表重叠问题
这个问题我之前做项目时也踩过坑!根源在于你用的是Matplotlib的全局pyplot接口(就是plt.xxx这类函数),在Django这种多请求并发的Web环境里,不同请求会共享这个全局状态——前一次绘图的残留元素(比如线条、数据点)没被彻底清理,就会和新请求的内容叠加在一起,导致图表混乱。
给你两个靠谱的解决方案,优先选第一个:
方案1:使用Matplotlib面向对象API(推荐)
放弃全局的plt,每次请求都创建独立的Figure和Axes对象,让每个请求的绘图环境完全隔离,从根源上避免状态共享问题。修改后的代码如下:
from matplotlib.figure import Figure import io import base64 # 创建独立的Figure,直接指定尺寸 fig = Figure(figsize=(12, 8)) ax = fig.add_subplot(111) # 用ax对象完成所有绘图操作,代替全局的plt ax.set_title("xyz") ax.plot(x, y, 'b') ax.plot(x, z, 'r') fig.tight_layout() # 将图表保存到BytesIO buf = io.BytesIO() fig.savefig(buf, format='png') # 显式关闭figure释放资源,避免内存泄漏 plt.close(fig) # 转base64生成HTML可用的图片地址 image_base64 = base64.b64encode(buf.getvalue()).decode('utf-8').replace('\n', '') img_src = f'data:image/png;base64, {image_base64}'
这种方式是Web环境下使用Matplotlib的最佳实践,完全避开了全局状态的干扰。
方案2:彻底清理全局状态(应急过渡用)
如果暂时不想大规模修改代码,那就要确保每次请求处理完后,彻底清除Matplotlib的全局状态——不止plt.clf(),还要加上plt.close('all')关闭所有残留的Figure对象:
plt.figure() plt.title("xyz") plt.tight_layout() plt.plot(x,y, 'b') plt.plot(x,z, 'r') buf = BytesIO() fig = plt.gcf() fig.set_size_inches(12,8, forward=True) fig.savefig(buf, format='png') # 先清除当前figure内容,再关闭所有figure彻底清理全局状态 plt.clf() plt.close('all') # 这行是关键! image_base64 = base64.b64encode( buf.getvalue()).decode('utf-8').replace('\n', '') img_src = 'data:image/png;base64, {}'.format(image_base64)
不过这个方案在高并发场景下还是有状态冲突的风险,所以优先推荐方案1。
内容的提问来源于stack exchange,提问作者devired
相关产品推荐
相关产品推荐

