Генерация изображения на лету с помощью FLask и matplotlib - PullRequest
0 голосов
/ 12 ноября 2018

Я хотел бы построить изображение без необходимости сохранять его в статической папке.

У меня есть пример, опубликованный пользователем Messa, который работает отлично:

import io
import random
from flask import Response
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure

@app.route('/plot.png')
def plot_png():
    fig = create_figure()
    output = io.BytesIO()
    FigureCanvas(fig).print_png(output)
    return Response(output.getvalue(), mimetype='image/png')

def create_figure():
    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)
    return fig

Затем в файле HTML:

<img src="/plot.png" alt="my plot">

Результат идеален. Я получаю изображение на лету.

Теперь я хотел бы использовать некоторые параметры, подобные этому:

@app.route('/<x_values_source>/<y_values_source>/plot.png')
def plot_png(x_values_source, y_values_source):
    fig = create_figure(x_values_source, y_values_source)
    output = io.BytesIO()
    FigureCanvas(fig).print_png(output)
    return Response(output.getvalue(), mimetype='image/png')

def create_figure(x_values_source, y_values_source):
    x_values = function_that_returns_x_values_set(x_values_source)
    y_values = function_that_returns_y_values_set(y_values_source)
    fig = Figure()
    axis = fig.add_subplot(1, 1, 1)
    axis.plot(x_values, y_values)
    return fig

Но, конечно, это не работает. Я довольно новичок в Python, и я до сих пор многому учусь.

Спасибо!

1 Ответ

0 голосов
/ 12 ноября 2018

Для передачи параметров лучше не добавлять их к URI, так как это может привести к путанице при декодировании маршрута Flask. Вместо этого, если вы сформируете URL как

/plot.png?x=1,2,3,4&y=100,200,300,400

вы можете забрать аргументы через request.args. Они будут представлены в виде строк, поэтому вам нужно разделить их и преобразовать в целые числа (или числа с плавающей запятой, если вы используете реальные числа)

from flask import request

@app.route('/plot.png')
def plot():
    try:
        x_values = [int(x) for x in request.args.get('x','').split(',')]
        y_values = [int(y) for y in request.args.get('y','').split(',')]
    except:
        # malformed 

У меня есть рабочий пример здесь надежного способа динамической обработки matplotlib. Общая идея

from flask import send_file

@app.route('/plot.png')
def plot_png():
    fig, ax = plt.subplots()
    draw(ax)
    return fig_response(fig)

def fig_response(fig):
    """Turn a matplotlib Figure into Flask response"""
    img_bytes = BytesIO()
    fig.savefig(img_bytes)
    img_bytes.seek(0)
    return send_file(img_bytes, mimetype='image/png')

, куда вы поставляете draw(). Взгляните, однако, на мой пример, поскольку вы хотите добавить несколько заголовков кэша.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...