Dynamisch in Python generierte Grafiken in HTML anzeigen

Django, Flask, Bottle, WSGI, CGI…
Lessi
User
Beiträge: 15
Registriert: Donnerstag 25. August 2022, 14:27

Ich habe die Lösung:

index.html:

Code: Alles auswählen

....
  <img id="graph" img src="">
...

Code: Alles auswählen

...
      document.getElementById("graph").src = data.img_tag
...
server.py:

Code: Alles auswählen

...
  img_tag = "data:image/png;base64," + str_equivalent_image
...
Danke für die Ideen und Hinweise!
Lessi
User
Beiträge: 15
Registriert: Donnerstag 25. August 2022, 14:27

noisefloor hat geschrieben: Donnerstag 25. August 2022, 19:44 Hallo,

musst oder willst du das so machen? Grundsätzlich kannst du ein BytesIO Objekt ja auch wie eine Datei ausliefern bzw. von der Webseite nachladen lassen. Dann brauchst du den Umweg über das Base64 Encoding nicht.

Gruß, noisefloor
Ich lasse das ganze später dann auf einem Rasperry Pi laufen. Da ich relativ häufig Daten lesen werde und somit oft ein Bild schreiben würde, wäre die SD Karte wohl schnell hinüber.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hier http://docs.bokeh.org/en/latest/docs/us ... erver.html steht, wie man damit und zB add_periodic_callback Daten im Browser updaten kann. Den Bokeh-Server kann man auch in einen bestehenden Webserver einbetten, wenn das denn ueberhaupt notwendig ist.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Lessi hat geschrieben: Freitag 26. August 2022, 14:45 Ich lasse das ganze später dann auf einem Rasperry Pi laufen. Da ich relativ häufig Daten lesen werde und somit oft ein Bild schreiben würde, wäre die SD Karte wohl schnell hinüber.
Dann kann man ja auch eine RAM-Disk bemuehen.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

@Lessi: keine Sorge, da wird nichts geschrieben. Bleibt meine Frage unbeantwortet, warum Du das so kompliziert über EventSource machst.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Sirius3 hat geschrieben: Freitag 26. August 2022, 14:55 @Lessi: keine Sorge, da wird nichts geschrieben.
Wobei eine BytesIO-Loesung ihre Tuecken hat, weil sie letztlich globalen Zustand braucht, bestenfalls ueber ein eigenes Woerterbuch mit zB einer GUID versehen. Das mit einer RAM-Disk zu machen ist ein bisschen einfacher, weil dann simple, statische Routen funktionieren.
Benutzeravatar
__blackjack__
User
Beiträge: 13117
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Lessi hat geschrieben: Freitag 26. August 2022, 14:28
Sirius3 hat geschrieben: Freitag 26. August 2022, 08:47 @Lessi: wie es in Deinem Fall funktioniert, habe ich Dir gezeigt. Ich weiß jetzt nicht, ob das bei Dir angekommen ist.
Das mit `innerText` ist bei Dir anscheinend auch nicht angekommen.
Neben den ganzen anderen Hinweisen zu Python-Konventionen noch eine: eingerückt wird immer mit vier Leerzeichen pro Ebene, nicht 2.
Auch wenn ich in meinem Code {img_tag} durch {{img_tag|safe}} ersetze funktioniert es nicht. Es wird für die Zeile nichts ausgegeben und im Quellcode steht eine leere Zeile. Kann es daran liegen, dass bei mir im Gegensatz zu deinem Code, img_tag erst später durch Listener gesetzt wird?
Das hatten wir doch schon mal: Entgegen Deiner Behauptung übergibst Du halt keinen Wert für `img_tag` an das Template. Wenn Du das tun würdest, wäre das nicht leer. Und das es leer ist, bedeutet das Du keinen Wert übergibst. Auch wenn Du das anscheinend nicht glaubst. Du hast auch noch keinen Code gezeigt bei dem Du dafür einen Wert übergeben würdest. Im Gegenteil, Du hast Code gezeigt in dem *kein* *einziger* Wert übergeben wird. Woher soll das dann auch kommen wenn das Template gerendert wird‽
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Lessi
User
Beiträge: 15
Registriert: Donnerstag 25. August 2022, 14:27

Sirius3 hat geschrieben: Freitag 26. August 2022, 14:55 @Lessi: keine Sorge, da wird nichts geschrieben. Bleibt meine Frage unbeantwortet, warum Du das so kompliziert über EventSource machst.
Habe keine bessere Lösung gefunden
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Da ich relativ häufig Daten lesen werde und somit oft ein Bild schreiben würde, wäre die SD Karte wohl schnell hinüber.
Um es nochmal klarer zu machen: BytesIO Objekte _sind_ im RAM und eben nicht auf einem Laufwerk. BytesIO gehört zu den "file-type objects", d.h. sie verhalten sich wie eine Datei bzw. können anstelle einer Datei genutzt werden, sind aber nicht wirklich ein.
Wobei eine BytesIO-Loesung ihre Tuecken hat, weil sie letztlich globalen Zustand braucht,
Wieso? Wenn die Webseite periodisch die URL abrufen, die die aktuelle Grafik abruft und die Grafik jedes mal "on the fly" neu generiert wird, braucht man doch keinen globalen Zustand?

Gruß, noisefloor
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@noisefloor: ich habe nicht weit genug gedacht. Natuerlich geht das auch ohne globalen Zustand, die Parameter zur Generierung muessen dann natuerilch einfach am img-src-Pfad angehangen werden. War also quatsch von mir.
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Lessi hat geschrieben: Freitag 26. August 2022, 17:07 Habe keine bessere Lösung gefunden
Dazu habe ich ja den passenden Code gepostet.
Lessi
User
Beiträge: 15
Registriert: Donnerstag 25. August 2022, 14:27

Sirius3 hat geschrieben: Freitag 26. August 2022, 07:15 Du malst ständig in den selben Plot, der wir also mit der Zeit ziemlich voll.

Wenn Du einen Film abspielen willst, dann ist Motion-JPEG, bzw. geht das auch mit Motion-PNG, das richtige, denn das unterstützt jeder Browser schon von sich aus, ganz ohne Javascript.
Hier werden die Daten auch Binär übertragen, so dass man die Konvertierung in base64 nicht braucht, was Bandbreite, Speicher und CPU spart.
Das ist korrekt. Ich erzeuge ja ein immer größer werdendes Bild, welches immer wieder neu erstellt und angezeigt wird. Ich zeichne aktuell 6 Kurven in einem Plot und es kommen zu jeder alle 2 Sekunden ein Punkt hinzu. Da wird mein Rasperry Pi 3 schon recht schnell recht langsam. Da wird mir auch wenig bringen, das Intervall etwas zu vergrößern. Eigentlich müsste man ja "nur" diese neuen Punkte hinzufügen. Geht das mit Motion-JPEG/PNG?
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein. Das sind immer nur volle Frames. Ich bringe da nochmal bokeh ins spiel, da macht der popelige Pi nämlich gar nix, sondern der (üblicherweise) deutlich leistungsstärkere Rechner, auf dem der Browser läuft.

Und warum baust du das ganze überhaupt? Alles 2 Sekunden ist ja eher lahm, da würde ich Grafana oder Telegraf ausprobieren.
Lessi
User
Beiträge: 15
Registriert: Donnerstag 25. August 2022, 14:27

Ich messe meinen privaten Stromverbrauch und die Stromerzeugung meiner kleinen PV Anlage. Diese möchte ich mitloggen (aktuell csv Dateien) und visualisieren. Die Kurven sollten halt "schnell" reagieren (2s sehe ich da mal als schnell genug an). Wenn ich mal einen Verbraucher hinzuschalte, die Waschmachine heizt oder eine Wolke um die Ecke kommt, möchte ich das nachvollziehen können.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Verstehe ich schon. Aber warum erfindest du das Rad neu? Grafana und Co sind fuer solche Zwecke doch geschaffen, und erledigen das ohne grosse Probleme - und mit mehr Features bezueglich zB Filterung und drill-down, als du es jemals bauen koennen wirst.
Lessi
User
Beiträge: 15
Registriert: Donnerstag 25. August 2022, 14:27

__deets__ hat geschrieben: Samstag 27. August 2022, 14:40 Verstehe ich schon. Aber warum erfindest du das Rad neu? Grafana und Co sind fuer solche Zwecke doch geschaffen, und erledigen das ohne grosse Probleme - und mit mehr Features bezueglich zB Filterung und drill-down, als du es jemals bauen koennen wirst.
Stimmt. Bin da auch schon dran. Grafana sieht wirklich gut aus
Antworten