Flask网页展示Matplotlib/Seaborn多图表时出现重叠问题求助
Flask页面多图表重叠问题解决
问题描述
使用Flask构建网页时,单独展示每个图表均正常,但在同一页面同时展示两个图表时出现重叠现象。
相关代码
main.py
@main.route('/filetypebarchart', methods=["GET"]) def filetypebarchart(): fig1 =plt.figure("1") df = pd.read_csv('./export_dataframe.csv') df.value_counts() fig1 = df.type.value_counts().plot(kind = 'barh').get_figure() fig1.savefig('./project/filetypebarchart.png') return send_file("filetypebarchart.png",mimetype='img/png') @main.route('/filetypesum', methods=["GET"]) def filetypesum(): fig2 = plt.figure("2") df = pd.read_csv('./export_dataframe.csv') fig2 = sns.barplot(data=df, x="type", y="size", estimator="sum", palette="pastel") fig2.figure.savefig('./project/filetypesum.png') return send_file("filetypesum.png",mimetype='img/png')
HTML代码
<div> <img src="/filetypebarchart" alt="Chart" height="auto" width="100%"> <br><br> <img src="/filetypesum" alt="Chart" height="auto" width="100%"> </div>
问题原因
Matplotlib默认使用全局绘图状态,连续创建图形时若未显式清理之前的画布,后续绘图操作会叠加到已有画布上,导致图表重叠。此外,原代码中先创建plt.figure()后又重新赋值给绘图返回的figure对象,之前的figure实例未被正确处理,也会引发状态残留问题。
解决方法
方法1:显式清理画布
在每个视图函数结束时关闭当前图形,避免状态残留:
import matplotlib.pyplot as plt import pandas as pd import seaborn as sns from flask import send_file @main.route('/filetypebarchart', methods=["GET"]) def filetypebarchart(): # 创建独立画布和坐标轴 fig1, ax = plt.subplots() df = pd.read_csv('./export_dataframe.csv') df.type.value_counts().plot(kind='barh', ax=ax) fig1.savefig('./project/filetypebarchart.png') # 关闭画布清理全局状态 plt.close(fig1) return send_file("./project/filetypebarchart.png", mimetype='img/png') @main.route('/filetypesum', methods=["GET"]) def filetypesum(): fig2, ax = plt.subplots() df = pd.read_csv('./export_dataframe.csv') sns.barplot(data=df, x="type", y="size", estimator="sum", palette="pastel", ax=ax) fig2.savefig('./project/filetypesum.png') plt.close(fig2) return send_file("./project/filetypesum.png", mimetype='img/png')
方法2:使用字节流直接返回(避免本地文件存储)
跳过保存到本地文件的步骤,直接将图形转为字节流返回,既避免文件覆盖、权限等问题,也能减少状态残留风险:
import io import matplotlib.pyplot as plt import pandas as pd import seaborn as sns from flask import send_file @main.route('/filetypebarchart', methods=["GET"]) def filetypebarchart(): fig, ax = plt.subplots() df = pd.read_csv('./export_dataframe.csv') df.type.value_counts().plot(kind='barh', ax=ax) # 将图形写入字节流 img_io = io.BytesIO() fig.savefig(img_io, format='png') img_io.seek(0) plt.close(fig) return send_file(img_io, mimetype='image/png') @main.route('/filetypesum', methods=["GET"]) def filetypesum(): fig, ax = plt.subplots() df = pd.read_csv('./export_dataframe.csv') sns.barplot(data=df, x="type", y="size", estimator="sum", palette="pastel", ax=ax) img_io = io.BytesIO() fig.savefig(img_io, format='png') img_io.seek(0) plt.close(fig) return send_file(img_io, mimetype='image/png')
关键注意点
- 始终使用
plt.close(fig)显式关闭每个创建的图形,清理Matplotlib的全局状态 - 推荐使用
plt.subplots()同时创建figure和axes对象,更清晰地控制绘图区域 - 避免重复赋值figure变量(比如原代码中先
fig1 = plt.figure()又重新赋值为plot返回的figure)
内容的提问来源于stack exchange,提问作者EvitaSchaap
相关产品推荐
相关产品推荐

