40 Stimmen

Übergabe einer matplotlib-Figur in HTML (Flask)

Ich verwende matplotlib, um in einer Web-App einige Abbildungen darzustellen. Ich habe fig.savefig() verwendet, als ich nur Skripte ausgeführt habe. Allerdings benötige ich eine Funktion, die ein tatsächliches ".png"-Bild zurückgibt, damit ich es in meinem HTML aufrufen kann.

Weitere (möglicherweise unnötige) Informationen: Ich verwende Python Flask. Ich dachte, ich könnte fig.savefig() verwenden und die Abbildung einfach in meinen statischen Ordner legen und sie dann von meinem HTML aufrufen, aber ich würde das lieber nicht jedes Mal tun. Es wäre optimal, wenn ich einfach die Abbildung erstellen könnte, ein Bild davon machen, dieses Bild zurückgeben und es von meinem HTML aufrufen könnte, dann wäre es weg.

Der Code, der die Abbildung erstellt, funktioniert. Allerdings gibt er eine Abbildung zurück, die anscheinend nicht mit HTML funktioniert.

Hier rufe ich draw_polygon im Routing auf, draw_polygon ist die Methode, die die Abbildung zurückgibt:

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

Und hier ist das HTML, in dem ich versuche, das Bild zu generieren.

    {{ title }} - Bild

Und, wie Sie wahrscheinlich erraten können, wenn ich die Seite lade, bekomme ich nur Platzhalterbild. Also mochten sie das Format nicht, in dem ich die Abbildung eingespeist habe.

Weiß jemand, welche matplotlib Methoden/Workarounds eine Abbildung in ein tatsächliches Bild umwandeln? Ich habe die Dokumentation durchsucht, aber ich finde nichts. Danke!

Übrigens: Ich dachte, es wäre nicht notwendig, den Python-Code einzuschließen, der die Abbildung erstellt, aber ich kann ihn einschließen, wenn ihr ihn sehen müsst (wollte die Frage nur nicht überladen)

37voto

Miguel Grinberg Punkte 60833

Sie müssen den HTML-Code und das Bild in zwei verschiedene Routen aufteilen.

Ihre /images/-Route wird nur die Seite anzeigen, und im HTML-Inhalt dieser Seite wird ein Verweis auf die zweite Route vorhanden sein, die das Bild anzeigt.

Das Bild wird in seiner eigenen Route von einer Speicherdatei aus bedient, die Sie mit savefig() generieren.

Ich habe das natürlich nicht getestet, aber ich glaube, dass das folgende Beispiel so funktioniert oder Sie zumindest nah an eine Lösung bringt:

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

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

Ihr images.html-Template wird dann wie folgt aussehen:

    {{ title }} - Bild

8voto

akkhil Punkte 379

Python 3

Ich hatte viele Probleme mit Fehlern wie - Aufgrund einer nicht behandelten Ausnahme 'NSInternalInconsistencyException' wird die App beendet, Begründung: 'NSWindow drag regions should only be invalidated on the Main Thread!

Für all diejenigen, die matplotlib mit Flask verwenden möchten und den Graphen auf einer HTML-Seite in Python 3 rendern wollen, hier ist die Lösung -

In der __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

heatmap - 

  Heatmap

7voto

Tim Seed Punkte 4633

Für Python3 ....

Ich habe einen DataFrame, ich möchte dieses Diagramm in Flask anzeigen ....

Erstellen Sie also ein Base64-Bild des Diagramms.

    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')

Jetzt rufe ich mein Template auf, indem ich die base64-kodierten Daten wie folgt verwende....

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

Der relevante Teil des Templates (d.h. der Bildabschnitt) sieht so aus....

 {% if sunalt != None %}

      Sonnenhöhe im Laufe des Jahres

{% endif %}

Hoffe, das hilft jemandem....

3voto

Rodolfo Alvarez Punkte 972

Ich arbeite mit Python 3.x, ich habe einige Zeilen des Codes geändert und es hat für mich funktioniert. Ich hatte folgende Fehlermeldung: ".....Objekt hat kein Attribut 'savefig'"

@app.route('/fig/')

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')

1voto

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')

Die anderen Antworten sind korrekt, ich wollte nur die Header-Dateien zeigen, die eingebunden werden müssen. Dieses Programm erstellt einen einfachen Graphen und sendet ihn an die HTML-Seite.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X