Python 从Flask中的JSON数据提供动态matplotlib图像
在我的应用程序中,我想为通过POST方法发送的numpy数组生成的PNG图像提供服务,因此在我提出的应用程序中,有两种途径——一种是为HTML提供Python 从Flask中的JSON数据提供动态matplotlib图像,python,json,image,matplotlib,flask,Python,Json,Image,Matplotlib,Flask,在我的应用程序中,我想为通过POST方法发送的numpy数组生成的PNG图像提供服务,因此在我提出的应用程序中,有两种途径——一种是为HTML提供'.format(img.getvalue())的途径 @app.route('/img/gen',methods=['POST']) def img_gen(): data=np.array(json.loads(request.get_json())) 图=plt.图() plt.plot(数据[0,:],c='b') plt.plot(数据[1,
'.format(img.getvalue())的途径
@app.route('/img/gen',methods=['POST'])
def img_gen():
data=np.array(json.loads(request.get_json()))
图=plt.图()
plt.plot(数据[0,:],c='b')
plt.plot(数据[1,:]*-1,c='r')
plt.grid()
png=BytesIO()
图Canvasagg(图)。打印png(png)
plt.关闭(图)
返回响应(png.getvalue(),mimetype='image/png')
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
app.run()
我检查了数组是否正确地传递给
/img/gen
路由并由其接收,但应用程序似乎卡在返回
行或之前。Gunicorn v3不打印任何错误消息,除了工作超时
。如果有人向我指出此问题的原因,我将不胜感激。您的代码有几个问题:
.raw.read()
直接访问字节响应,但是由于响应是mimetype“img/png”,您只需使用.content
。我无法使.raw.read()
正常工作,因此我建议使用`b'
将附加在开头,而'
将附加在结尾。此外,python字节类型不是base64,请使用base64
模块中的b64encode
src=
。
基于2、3和4,您应该编写以下代码:b'%b64encode(img)
,它使用字节类型,声明数据类型,并插入base64 bytestringfrom flask import Flask, request, url_for, Response
import requests
from matplotlib import pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg
import numpy as np
import json
from io import BytesIO
app = Flask(__name__)
@app.route('/img/show')
def show_html():
data = np.random.rand(80).reshape((2, 40))
img = BytesIO(requests.post(request.scheme + '://' + request.host + url_for('img_gen'), json=json.dumps(data.astype(float).tolist())).raw.read())
return '<img src="{}" />'.format(img.getvalue())
@app.route('/img/gen', methods=['POST'])
def img_gen():
data = np.array(json.loads(request.get_json()))
fig = plt.figure()
plt.plot(data[0, :], c='b')
plt.plot(data[1, :]*-1, c='r')
plt.grid()
png = BytesIO()
FigureCanvasAgg(fig).print_png(png)
plt.close(fig)
return Response(png.getvalue(), mimetype='image/png')
if __name__ == '__main__':
app.run()
从烧瓶导入烧瓶,请求,url\u,响应
导入请求
从matplotlib导入pyplot作为plt
从matplotlib.backends.backend_agg导入图Canvasagg
将numpy作为np导入
导入json
从io导入字节io
从base64导入b64encode
app=烧瓶(名称)
@应用程序路线(“/img/show”)
def show_html():
数据=np.random.rand(80).重塑((2,40))
img=requests.post(
request.scheme+“:/”+request.host+url\u for(“img\u gen”),
json=json.dumps(data.astype(float.tolist()),
).内容
返回b“”%B64编码(img)
@app.route(“/img/gen”,methods=[“POST”])
def img_gen():
data=np.array(json.loads(request.get_json()))
图=plt.图()
plt.绘图(数据[0,:],c=“b”)
plt.绘图(数据[1,:]*-1,c=“r”)
plt.grid()
png=BytesIO()
图Canvasagg(图)。打印png(png)
plt.关闭(图)
返回响应(png.getvalue(),mimetype=“image/png”)
如果名称=“\uuuuu main\uuuuuuuu”:
app.run()
最后,我将注意到,您不一定需要为映像使用单独的端点,因为该端点仅由服务器本身使用。假设您没有调用外部服务器,那么让一个函数返回图像会更有意义,该函数由
show\u html
函数调用。您的最后一句话表明您向响应发送了意外数据。您是否分别测试了img\U gen的功能,以查看它是否可以显示保存为静态文件的图像?这不是对你问题的回答,但你是否考虑过将图像保存到一个临时文件中,然后提供给它?@Kaan E。我测试了这段代码,类似的功能适用于GET请求生成的PNG图像。我从感谢您的回答中学到了这段代码,但是您提出的代码仍然不适用于我-每次我点击/img/show
端点时,我都会收到工人超时。我使用的是gunicorn-3(版本19.9.0)
@mac13k,我目前使用的是windows,因此无法测试gunicorn(我使用flask的内置服务器进行了测试)。不过,这可能会有所帮助。它猜测工作超时是因为生成图像和发送响应所花费的时间太长。我编写了另一个应用程序,在GET请求时以PNG格式生成matplotlib绘图,它工作正常-没有超时,图像也正常。在那里,我可以直接在
中包含指向端点的URL,而无需存储或处理响应,因此我猜在这种情况下,我们试图显示请求的方式有问题。post().content
在HTML中。我修改了另一个应用程序,该应用程序在直接从URL提供图像服务时运行良好-使用requests.get()
它开始超时,所以这就是问题出现的地方,但我不明白为什么…@mac13k,我刚刚用gunicorn进行了测试,发现了问题。运行gunicorn main:app
默认情况下只使用一个工作进程-这意味着它一次只能处理一个请求,但要使此代码正常工作,您至少需要运行两个工作进程,因为您需要同时调用两个端点。因此,show
端点将永远等待gen
端点。尝试运行gunicorn-w2 main:app,它应该可以工作。
from flask import Flask, request, url_for, Response
import requests
from matplotlib import pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg
import numpy as np
import json
from io import BytesIO
from base64 import b64encode
app = Flask(__name__)
@app.route("/img/show")
def show_html():
data = np.random.rand(80).reshape((2, 40))
img = requests.post(
request.scheme + "://" + request.host + url_for("img_gen"),
json=json.dumps(data.astype(float).tolist()),
).content
return b'<img src="data:image/png;base64,%b" />' %b64encode(img)
@app.route("/img/gen", methods=["POST"])
def img_gen():
data = np.array(json.loads(request.get_json()))
fig = plt.figure()
plt.plot(data[0, :], c="b")
plt.plot(data[1, :] * -1, c="r")
plt.grid()
png = BytesIO()
FigureCanvasAgg(fig).print_png(png)
plt.close(fig)
return Response(png.getvalue(), mimetype="image/png")
if __name__ == "__main__":
app.run()