Flask服务返回Matplotlib图片异常:富格式绘图无法渲染
问题分析与解决方案
嘿,我一眼就看出问题所在了——你在PltGraph里混用了matplotlib的面向对象接口和pyplot状态机,导致绘图和最终输出的不是同一个figure对象,才会返回空白图片。
核心问题拆解
你创建了自己的fig = Figure(),但后面调用plt.plot()、plt.ylabel()这些pyplot函数时,其实是在操作matplotlib自动生成的全局默认figure,而不是你定义的fig。最后你把空的fig传给FigureCanvas,自然输出的是空白图片。
两种可行的解决方法
方法一:全程使用面向对象接口(推荐)
这种方式不依赖全局状态,更适合Web应用的多请求场景,避免不同请求之间的干扰:
class PltGraph(Resource): def get(self): fig = Figure() # 获取子图对象,后续所有操作都基于这个对象 axis = fig.add_subplot(1, 1, 1) xs = range(100) ys = [random.randint(1, 50) for x in xs] axis.plot(xs, ys) # 用axis的set_*方法设置标签和标题 axis.set_ylabel("Y label") axis.set_xlabel("X label") axis.set_title("x and y") canvas = FigureCanvas(fig) output = BytesIO() canvas.print_png(output) response = make_response(output.getvalue()) response.mimetype = 'image/png' return response
方法二:如果想继续用pyplot状态机
如果习惯了pyplot的写法,记得要获取当前正在操作的figure,并且在请求结束后清理资源,避免状态残留:
class PltGraph(Resource): def get(self): # 先清空之前的figure,防止上一次请求的内容残留 plt.clf() xs = range(100) ys = [random.randint(1, 50) for x in xs] plt.plot(xs, ys) plt.ylabel("Y label") plt.xlabel("X label") plt.title("x and y") # 获取当前正在操作的figure对象 fig = plt.gcf() canvas = FigureCanvas(fig) output = BytesIO() canvas.print_png(output) response = make_response(output.getvalue()) response.mimetype = 'image/png' # 关闭figure,释放内存资源 plt.close(fig) return response
额外提醒
在Flask这类多线程/多请求的Web应用中,优先使用面向对象接口会更安全,因为pyplot的全局状态可能会在不同请求之间串数据,导致意想不到的绘图错误。
内容的提问来源于stack exchange,提问作者Vineet
相关产品推荐
相关产品推荐

