Python 将 matplotlib 图传递给 HTML(烧瓶)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20107414/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 19:32:29  来源:igfitidea点击:

Passing a matplotlib figure to HTML (flask)

pythonhtmlimagematplotlibflask

提问by Alex Chumbley

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.

我正在使用 matplotlib 在 Web 应用程序中渲染一些图形。我以前fig.savefig()在运行脚本时使用过。但是,我需要一个函数来返回一个实际的“.png”图像,以便我可以用我的 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.

更多(可能是不必要的)信息:我正在使用 Python Flask。我想我可以使用fig.savefig()并将图形粘贴在我的静态文件夹中,然后从我的 HTML 中调用它,但我不想每次都这样做。如果我可以创建图形,从中制作图像,返回该图像,然后从我的 HTML 中调用它,那将是最佳选择,然后它就会消失。

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

创建图形的代码有效。但是,它返回一个数字,我猜它不适用于 HTML。

Here's where I call the draw_polygonin the routing, draw_polygonis the method that returns the figure:

这是我draw_polygon在路由中调用的地方,draw_polygon是返回图形的方法:

@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。

<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.

而且,正如您可能猜到的,当我加载页面时,我得到的只是Image Placeholder. 所以,他们不喜欢我输入的格式。

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!

任何人都知道哪些 matplotlib 方法/变通方法将图形转换为实际图像?我到处都是这些文档,但我找不到任何东西。谢谢!

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)

顺便说一句:认为没有必要包含制作图形的python代码,但如果你们需要看到它,我可以包含它(只是不想把问题弄乱)

采纳答案by Miguel

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

您必须将 HTML 和图像分成两个不同的路径。

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.

您的/images/<cropzonekey>路由将只为页面提供服务,并且在该页面的 HTML 内容中将引用第二个路由,即提供图像的路由。

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

该图像从您使用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.htmltemplate the becomes:

您的images.html模板将变为:

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

回答by Rodolfo Alvarez

I am working with Python 3.x, I have changed some lines of the code and it worked for me. I had the following error message: ".....object has no attribute 'savefig'"

我正在使用 Python 3.x,我更改了一些代码行,它对我有用。我收到以下错误消息:“.....object has no attribute 'savefig'”

@app.route('/fig/<cropzonekey>')

def fig(cropzonekey):
    #fig = draw_polygons(cropzonekey)
    fig = plt.plot([1,2,3,4], [1,2,3,4])
    #img = StringIO()
    img = BytesIO()
    #fig.savefig(img)
    plt.savefig(img)
    img.seek(0)
    return send_file(img, mimetype='image/png')

回答by Sneha Ravichandran

from flask import Flask, send_file
from io import StringIO
import matplotlib.pyplot as plt
from StringIO import StringIO
@app.route('/fig/')
def fig():
      plt.plot([1,2,3,4], [1,2,3,4])
      img = StringIO()
      plt.savefig(img)
      img.seek(0)
      return send_file(img, mimetype='image/png')

The other answers are correct ,I just wanted to show the header files that has to be included. This program creates a simple graph and sends it over to the html page.

其他答案是正确的,我只是想显示必须包含的头文件。该程序创建一个简单的图形并将其发送到 html 页面。

回答by Tim Seed

For Python3 ....

对于 Python3 ....

I have a DataFrame, I want to show this plot in Flask ....

我有一个 DataFrame,我想在 Flask 中显示这个图......

So Create a Base64 Image of the plot.

因此,创建绘图的 Base64 图像。

    df_week_min_az = pd.DataFrame.from_dict(week_max_az.to_dict(),
                                            orient='index', columns=['min_az'])



    sunalt = df_week_max_angle.plot().get_figure()
    buf = io.BytesIO()
    sunalt.savefig(buf, format='png')
    buf.seek(0)
    buffer = b''.join(buf)
    b2 = base64.b64encode(buffer)
    sunalt2=b2.decode('utf-8')

I now call my template using the base64 encoded data like this....

我现在使用这样的 base64 编码数据调用我的模板......

return render_template('where.html', form=form, sunalt=sunalt2)

return render_template('where.html', form=form, sunalt=sunalt2)

The relevant part of the template (i.e. the picture bit) looks like this....

模板的相关部分(即图片位)看起来像这样......

 {% if sunalt != None %}

      <h2>Sun Altitude during the year</h2>
    <img src="data:image/png;base64,{{ sunalt }}">
{% endif %}

Hope that helps someone....

希望能帮助某人....

回答by akkhil

Python 3

蟒蛇 3

I went through a lot of trouble with errors like - Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSWindow drag regions should only be invalidated on the Main Thread!

我遇到了很多错误,比如 - Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'NSWindow drag regions should only be invalidated on the Main Thread!

For all those who want to use matplotlib with flask and render the graph on an html page in python 3, here you go -

对于所有想要在 Flask 中使用 matplotlib 并在 python 3 的 html 页面上渲染图形的人,这里是 -

In the __init__.py

在里面 __init__.py

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
from flask import Flask, render_template
from io import BytesIO
import base64

    @app.route('/plot')
    def plot():
        img = BytesIO()
        y = [1,2,3,4,5]
        x = [0,2,1,3,4]

        plt.plot(x,y)

        plt.savefig(img, format='png')
        plt.close()
        img.seek(0)
        plot_url = base64.b64encode(img.getvalue()).decode('utf8')

        return render_template('plot.html', plot_url=plot_url)

In flaskr/templates/plot.html

flaskr/templates/plot.html

<!doctype html>
<title>heatmap - </title>
<section>
  <h2>Heatmap</h2>
  <img src="data:image/png;base64, {{ plot_url }}">
</section>