Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
314 views
in Technique[技术] by (71.8m points)

python - Passing a matplotlib figure to HTML (flask)

I am using matplotlib to render some figure in a web app. I've used fig.savefig() before when I'm just running scripts. However, I need a function to return an actual ".png" image so that I can call it with my HTML.

Some more (possibly unnecessary) info: I am using Python Flask. I figure I could use fig.savefig() and just stick the figure in my static folder and then call it from my HTML, but I'd rather not do that every time. It would be optimal if I could just create the figure, make an image out of it, return that image, and call it from my HTML, then it goes away.

The code that creates the figure works. However, it returns a figure, which doesn't work with HTML I guess.

Here's where I call the draw_polygon in the routing, draw_polygon is the method that returns the figure:

@app.route('/images/<cropzonekey>')
def images(cropzonekey):
    fig = draw_polygons(cropzonekey)
    return render_template("images.html", title=cropzonekey, figure = fig)

And here is the HTML where I am trying to generate the image.

<html>
  <head>
    <title>{{ title }} - image</title>
  </head>
  <body>
    <img src={{ figure }} alt="Image Placeholder" height="100">
  </body>
</html>

And, as you can probably guess, when I load the page, all I get is Image Placeholder. So, they didn't like the format I fed the figure in with.

Anyone know what matplotlib methods/work-arounds turn a figure into an actual image? I am all over these docs but I can't find anything. Thanks!

BTW: didn't think it was necessary to include the python code that makes the figure, but I can include it if You guys need to see it (just didn't want to clutter the question)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have to separate the HTML and the image into two different routes.

Your /images/<cropzonekey> route will just serve the page, and in the HTML content of that page there will be a reference to the second route, the one that serves the image.

The image is served in its own route from a memory file that you generate with savefig().

I obviously didn't test this, but I believe the following example will work as is or will get you pretty close to a working solution:

@app.route('/images/<cropzonekey>')
def images(cropzonekey):
    return render_template("images.html", title=cropzonekey)

@app.route('/fig/<cropzonekey>')
def fig(cropzonekey):
    fig = draw_polygons(cropzonekey)
    img = StringIO()
    fig.savefig(img)
    img.seek(0)
    return send_file(img, mimetype='image/png')

Your images.html template the becomes:

<html>
  <head>
    <title>{{ title }} - image</title>
  </head>
  <body>
    <img src="{{ url_for('fig', cropzonekey = title) }}" alt="Image Placeholder" height="100">
  </body>
</html>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...