Matplotlib und Bottel

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Warum kommst du jetzt auf static_file, wo du doch nun extra matplotlib dazu gebracht hast, KEINE Datei zu speichern?

sowas wie (ungetestet)

Code: Alles auswählen

def index():
    from schnitt_test import schnittkraefte
    
    s = schnittkraefte(3, 2.25, 26700000., 5, 10, 30, 10, 20, 20, 20)
    return "Content-Type: image/png\n" + s
sollte es doch tun.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Rebecca hat geschrieben:Warum kommst du jetzt auf static_file, wo du doch nun extra matplotlib dazu gebracht hast, KEINE Datei zu speichern?

sowas wie (ungetestet)

Code: Alles auswählen

def index():
    from schnitt_test import schnittkraefte
    
    s = schnittkraefte(3, 2.25, 26700000., 5, 10, 30, 10, 20, 20, 20)
    return "Content-Type: image/png\n" + s
sollte es doch tun.
Ich hab gedacht, dass man so den Type übergeben kann.

Wenn ich das so probiere wie du das gesagt hast, bekomme ich das Bild kryptisch ausgegeben (so wies sonst in der Konsole war).

Bild

Ich hab dann doch noch eine weitere Frage zu der return Anweisung.
Wenn man eine komplette Seite mit Bildern etc. ausgeben will, muss man sich den String mit Bildern vorher zusammen bauen und dann diesen zurück geben ? Wie würde ich dann in diesem Fall das dynamisch generierte Bild dort unterbringen?

gruß
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Naja, das ist ja schonmal einen Schritt weiter. OK, den Content-Type an den String zu klatschen war offensichtlich Bloedsinn, aber schau dir mal das Response-Objekt an...
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Rebecca hat geschrieben:Naja, das ist ja schonmal einen Schritt weiter. OK, den Content-Type an den String zu klatschen war offensichtlich Bloedsinn, aber schau dir mal das Response-Objekt an...
Vielen Dank für den Hinweis, jetzt funktioniert es endlich Bild

Code: Alles auswählen

from bottle import route, run, static_file, debug, response

@route('/')
@route('/index.html')
def index():
    from schnitt_test import schnittkraefte
    
    s = schnittkraefte(3, 2.25, 26700000., 5, 10, 30, 10, 20, 20, 20)
    response.headers['Content-Type'] = 'image/png'
    return s
  
debug(True)
run(host='localhost', port=8080)
Jetzt hab ich aber noch weitere Fragen :mrgreen:
Wenn das Bild ausgegeben wurde, bleibt das dann im Arbeitsspeicher oder wird das dann automatisch gelöscht? Weil wenn das Programm auf einem Server ständig läuft, wäre ja irgendwann der Arbeitsspeicher voll :lol:

Ein weiteres Anliegen von mir, dass ich nicht nur Bilder ausgeben möchte, sondern halt eine gesamte Webseite. Jetzt habe ich den Header verändert, so dass der Browser annimmt dass da nur ein Bild kommt. Wie kann ich denn Bilder und Text verschicken?

gruß
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

mathman hat geschrieben:Wenn das Bild ausgegeben wurde, bleibt das dann im Arbeitsspeicher oder wird das dann automatisch gelöscht? Weil wenn das Programm auf einem Server ständig läuft, wäre ja irgendwann der Arbeitsspeicher voll :lol:
Das Objekt bleibt so lange im Speicher wie lange es noch Referenzen drauf gibt. Wie jedes Objekt in Python eben :roll:
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Leonidas hat geschrieben:
mathman hat geschrieben:Wenn das Bild ausgegeben wurde, bleibt das dann im Arbeitsspeicher oder wird das dann automatisch gelöscht? Weil wenn das Programm auf einem Server ständig läuft, wäre ja irgendwann der Arbeitsspeicher voll :lol:
Das Objekt bleibt so lange im Speicher wie lange es noch Referenzen drauf gibt. Wie jedes Objekt in Python eben :roll:
Ok :D

Jetzt wäre nur noch das Problem wie ich das Bild und html Code an den Nutzer schicken könnte ...
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Na, eine Route für's HTML, und eine für das Bild. Im Template der HTML-Route verweist du im Bild-Element (das <img - Ding ;) ) für dein Bild auf die Bild-Route und fertig.
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

frabron hat geschrieben:Na, eine Route für's HTML, und eine für das Bild. Im Template der HTML-Route verweist du im Bild-Element (das <img - Ding ;) ) für dein Bild auf die Bild-Route und fertig.
Ok das funktioniert soweit :mrgreen:

Code: Alles auswählen

from bottle import route, run, static_file, debug, response
@route('/')
@route('/index.html')
def index():
    
    return """
    <p><img src="bild.png" alt="Plot"></p>
    """
@route('/bild.png')
def plot_schnittkraefte():
    from schnitt_test import schnittkraefte
    s = schnittkraefte(3, 2.25, 26700000., 5, 10, 30, 10, 20, 20, 20)
    from plot import plot_schnittkraefte
    s = plot_schnittkraefte(s)
    response.headers['Content-Type'] = 'image/png'
    return s
  
debug(True)
run(host='localhost', port=8080)
Jetzt besteht das Problem darin, dass ich z.B. die Daten aus der Funktion "schnittkraefte" zum plotten und für die Ausgabe auf der HTML Seite brauche.

Dafür reicht es ja die Werte einmal berechnen zu lassen. Diese würde ich dann in eine Variable speichern und und dann übergeben.

Code: Alles auswählen

from bottle import route, run, static_file, debug, response
from schnitt_test import schnittkraefte
s = schnittkraefte(3, 2.25, 26700000., 5, 10, 30, 10, 20, 20, 20)

@route('/')
@route('/index.html')
def index():
    return """
    <p><img src="bild.png" alt="Plot"></p>
    """
  
@route('/bild.png')
def plot_schnittkraefte(s):
    from plot import plot_schnittkraefte
    s = plot_schnittkraefte(s)
    response.headers['Content-Type'] = 'image/png'
    return s
  
debug(True)
run(host='localhost', port=8080)
Leider funktioniert das so nicht. Gibt es da einen Weg alle Werte im Vorfeld zu berechnen und diese dann zu übergeben ?

gruß
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Man könnte zum Beispiel die Bild-URL mit den gewünschten Parametern versehen.
Das Leben ist wie ein Tennisball.
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

EyDu hat geschrieben:Man könnte zum Beispiel die Bild-URL mit den gewünschten Parametern versehen.
Meinst du damit, das ich mit dem Bild eine Dynamische Route erzeugen soll?
Das Problem dabei ist, dass s eine 32 x 32 Matrix ist und man das sicherlich schlecht übergeben kann
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

So komplexe Datenstrukturen lassen sich eher schlecht übergeben, da in der HTTP - Welt nur Textdaten existieren. Du kannst also deine Matrix als String realisieren und der Plot-Funktion mittels POST unterjubeln (für GET ist der String dann wahrscheinlich zu lang), oder du berechnest in jeder Funktion deine Schnittkräfte neu. Diesen Weg würde ich auch vorschlagen, da so beide Funktionen entkoppelt sind und du die Plot-Funktion auch ohne HTML aufrufen kannst.

Du kannst dann ja deine Parameter (3, 2.25, 26700000., 5, 10, 30, 10, 20, 20, 20) entweder als GET Parameter der URL anhängen, oder wie EyDu vorschlägt, als URL Parameter

Code: Alles auswählen

from bottle import url

@route('/details/param1/:param1/param2/:param2/....')
def details(param1, param2, ....):
    # mach was
    schnittkraefte(param1, param2, ....)
    return '<img src="{url}">'.format({'url': url(plot, param1, param2, ....)})

@route('/plot/param1/:param1/param2/:param2/....')
def plot(param1, param2, ....):
    # plotte was


Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Das Problem ist, dass um die Eingangswerte für die Funktion Schnittkräfte noch zahlreiche Funktionen vor geschallten werden müssen um diese zu erhalten :roll:

Hier zum Beispiel wird automatisch nen Spruch generiert. Das Muster für das Bild sieht wie folgt aus:

http://www.sloganizer.net/bild,Python,orange,blau.png

Demnach wird mit Sicherheit eine Funktion dahinter stehen, die mittels "," den Namen trennt und daraus die Werte zur weiteren Verarbeitung generiert.

Könnte man dann nicht wie folgt vorgehen :D

<img src="{url}/4/1,2,3,4/1,2,3,4/1,2,3,4/1,2,3,4"/>

der erste Parameter bedeutet, dass es sich um eine 4 x 4 Matrix handelt.
Danach werden die weiteren Parameter zerlegt, da durch "," getrennt.
Im darauf folgenden Schritt wird dann aus den Werten eine 4 x 4 Matrix gemacht.
Dadurch habe ich dann wieder eine 4 x 4 Matrix. Ist so was möglich oder völliger Quatsch ?
frabron
User
Beiträge: 306
Registriert: Dienstag 31. März 2009, 14:36

Probier's doch mal aus ;)
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

So, hab mir da mal was zusammen geschrieben,
funktioniert aber leider nicht :K

Code: Alles auswählen

from bottle import route, run, static_file, debug, response, url

@route('/')
def index():
    pass

@route('/bild.png/:dim/:z1/:z2/:z3/:z4')
def plot_schnittkraefte(dim, z1, z2, z3, z4):
    matrix = []
    
    if dim == "4":
      #zerlgen von z1
      z1 = z1.split(',')
      #zerlegen von z2
      z2 = z2.split(',')
      #zerlegen von z3
      z3 = z3.split(',')
      #zerlegen von z4
      z4 = z4.split(',')
      #zusammfuegen zu Matrix
      matrix.append(z1)
      matrix.append(z2)
      matrix.append(z3)
      matrix.append(z4)
    
    from plot import plot_schnittkraefte
    
    s = plot_schnittkraefte(matrix)
    response.headers['Content-Type'] = 'image/png'
    return s
  
debug(True)
run(host='localhost', port=8080)
mit der Fehlermeldung
Traceback (most recent call last):
File "/home/mkoenig/workspace/sb2brain/src/web_test_matrix.py", line 7, in <module>
@route('/bild.png/:dim/:z1/:z2/:z3/:z4')
File "/home/mkoenig/workspace/sb2brain/src/bottle.py", line 460, in wrapper
self.routes.compile()
File "/home/mkoenig/workspace/sb2brain/src/bottle.py", line 355, in compile
raise RouteSyntaxError("Could not add Route: %s (%s)" % (route, e))
bottle.RouteSyntaxError: Could not add Route: <Route('bild.png/:dim/:z1/:z2/:z3/:z4') /> (redefinition of group name 'z' as group 4; was group 3)
Was mach ich denn falsch, hab mich eigentlich am Tutorial gehalten ...
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Ist so was möglich oder völliger Quatsch ?
Ab einer bestimmten Komplexität der Parameter, die hier IMHO überschritten ist, sollte man lieber ein HTML-Seite (z.B. generiert aus einem Bottle-Template) mit einem HTML-Formular zur Dateneingabe vorschalten.

Gruß, noisefloor
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

noisefloor hat geschrieben:Hallo,
Ist so was möglich oder völliger Quatsch ?
Ab einer bestimmten Komplexität der Parameter, die hier IMHO überschritten ist, sollte man lieber ein HTML-Seite (z.B. generiert aus einem Bottle-Template) mit einem HTML-Formular zur Dateneingabe vorschalten.

Gruß, noisefloor
Das soll ja auch geschehen. Der Nutzer gibt in einer Eingabemaske die Daten ein und der Server berechnet
dann die Ergebnisse, gibt diese dann in einem HTML Gerüst wieder aus.
Dazu sollen dann dynamisch Bilder (Plots aus mathplot) generiert werden. So wie ich das jetzt dem Thread entnommen habe, muss man das Bild in einer extra Route genieren lassen. Da sehr viele Berechnungen für den Pöot vorangehen möchte ich nicht 5 x die selben Berechnungen durchführen. Also muss ich der Route für den Plot doch irgendwie die Daten zum plotten übertragen ?!

Alternative wäre evtl. das Bild auf dem Server abzulegen. Problem dabei könnte aber sein, das die Berechnungen noch nicht abgeschlossen sind, ein zweiter Nutzer die Berechnungen startet und die Bilder dann vom ersten Nutzer vom zweiten überschrieben werden. Somit würde Nutzer 1 die Bilder vom Nutzer 2 erhalten :mrgreen:
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

ich habe mir jetzt 2000 Zahlen die mit Kommata getrennt sind erzeugt.
Danach habe ich diese in der URL an gehangen

http://localhost:8080/bild/0,1,2,3,4,5,6....

Auf dem Server läuft dazu folgendes Skript

Code: Alles auswählen

from bottle import route, run, static_file, debug, response, url

@route('/')
def index():
    pass

@route('bild/:z')
def plot_schnittkraefte(z):
    
    #zerlgen von z
    z1 = z.split(',')

    return z1[1999]
  
debug(True)
run(host='localhost', port=8080)
Somit konnte ich mir den Wert von dem 1999 Element wieder geben.
Leider hat es nicht geklappt dass man mehrere dynamische Routen gleichzeitig nutzen kann,
aber hier könnte ich ja ein paar Infos zu dem String für die später Bearbeitung mitliefern, so dass z.B. der erste Wert die Dimension der Matrix ist. :mrgreen:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Wieso übergibst Du die Daten nicht in einer Struktur, die sich vorher serialisieren lässt? Also als einfachstes eben als CSV-String, oder JSON, o.ä.? Damit hättest Du nur noch einen Parameter...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Benutzeravatar
mathman
User
Beiträge: 92
Registriert: Mittwoch 19. November 2008, 08:27
Wohnort: Magdeburg
Kontaktdaten:

Guten Abend :mrgreen:

ich habe mir mal Json im Netz angeschaut und das klingt sehr viel versprechend :)
Leider komme ich noch nicht damit klar. Ich möchte mein Array in Json Encodieren lassen.

Code: Alles auswählen

In [69]: a = numpy.array([[4,5,6],[7,8,9]])

In [70]: a
Out[70]: 
array([[4, 5, 6],
       [7, 8, 9]])

In [71]: json.encoder("name", a)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)

/home/mkoenig/<ipython console> in <module>()

TypeError: 'module' object is not callable
Wenn ich die Dokus richtig interpretiere müsste daraus folgendes kommen
{
"typ" : "1",
"name" : [[4, 5, 6],
[7, 8, 9]]
}
und das ganze kann ich als string dann der route übergeben und dann sollte ein Modul mir das wieder entpacken.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Ich bin mir nicht sicher ob ``json`` mit Numpy-Arrays zurechtkommt, vermutlich musst du diese in Listen konvertieren.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten