Ich verwende matplotlib, um eine Figur in einer Web-App zu rendern. Ich habe fig.savefig() schon einmal verwendet, wenn ich nur Skripte ausführe. Ich benötige jedoch eine Funktion, um ein tatsächliches ".png" -Bild zurückzugeben, damit ich es mit meinem HTML aufrufen kann.

Weitere (möglicherweise unnötige) Informationen: Ich verwende Python Flask. Ich denke, ich könnte fig.savefig() verwenden und die Figur einfach in meinen statischen Ordner stecken und sie dann aus meinem HTML-Code aufrufen, aber ich würde das lieber nicht jedes Mal tun. Es wäre optimal, wenn ich nur die Figur erstellen, ein Bild daraus machen, das Bild zurückgeben und es aus meinem HTML-Code aufrufen könnte, dann verschwindet es.

Der Code, der die Figur erstellt, funktioniert. Es wird jedoch eine Zahl zurückgegeben, die mit HTML vermutlich nicht funktioniert.

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

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

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

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

Und wie Sie wahrscheinlich erraten können, erhalte ich beim Laden der Seite nur Image Placeholder. Das Format, mit dem ich die Figur eingegeben habe, gefiel ihnen also nicht.

Weiß jemand, welche Matplotlib-Methoden / Workarounds eine Figur in ein tatsächliches Bild verwandeln? Ich bin überall in diesen Dokumenten, aber ich kann nichts finden. Vielen Dank!

Übrigens: Ich hätte nicht gedacht, dass es notwendig ist, den Python-Code aufzunehmen, aus dem die Figur besteht, aber ich kann ihn einschließen, wenn ihr ihn sehen müsst (wollte die Frage einfach nicht überladen).

35
Alex Chumbley 21 Nov. 2013 im 01:28

4 Antworten

Beste Antwort

Sie müssen HTML und Bild in zwei verschiedene Routen unterteilen.

Ihre /images/<cropzonekey> Route dient nur der Seite, und im HTML-Inhalt dieser Seite befindet sich ein Verweis auf die zweite Route, die das Bild bedient.

Das Bild wird auf einer eigenen Route aus einer Speicherdatei bereitgestellt, die Sie mit savefig() generieren.

Ich habe dies offensichtlich nicht getestet, aber ich glaube, dass das folgende Beispiel so funktioniert, wie es ist, oder Sie einer funktionierenden Lösung ziemlich nahe bringt:

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

Ihre images.html Vorlage wird zu:

<html>
  <head>
    <title>{{ title }} - image</title>
  </head>
  <body>
    <img src="{{ url_for('fig', cropzonekey = title) }}" alt="Image Placeholder" height="100">
  </body>
</html>
32
Miguel 20 Nov. 2013 im 22:02

Für Python3 ....

Ich habe einen DataFrame, ich möchte diesen Plot in Flask zeigen ....

Erstellen Sie also ein Base64-Image des Plots.

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

Ich rufe jetzt meine Vorlage mit den Base64-codierten Daten wie folgt auf ....

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

Der relevante Teil der Vorlage (d. H. Das Bildbit) sieht folgendermaßen aus ....

 {% if sunalt != None %}

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

Hoffe das hilft jemandem ....

5
Tim Seed 26 Juli 2018 im 07:30

Ich arbeite mit Python 3.x, ich habe einige Zeilen des Codes geändert und es hat bei mir funktioniert. Ich hatte die folgende Fehlermeldung: "..... Objekt hat kein Attribut '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')
3
Rodolfo Alvarez 25 Jän. 2018 im 18:20
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 richtig, ich wollte nur die Header-Dateien anzeigen, die enthalten sein müssen. Dieses Programm erstellt ein einfaches Diagramm und sendet es an die HTML-Seite.

2
Sneha Ravichandran 9 Mai 2018 im 08:21