Mit Werkzeug PNG aus sql Datenbank lesen und anzeigen

Django, Flask, Bottle, WSGI, CGI…
Antworten
heinrich75
User
Beiträge: 7
Registriert: Donnerstag 10. Februar 2011, 15:03

Ich möchte gerne eine Png Datei aus einer sql Datenbank lesen und diese als Response an Werkzeug zurückgeben.

Leider erzeugt mein Programmcode folgenden Fehler:
"IOError: encoder png not available"

Pil wurde mit dem Windows Installer installiert, meine Platform ist python2.6 und WinXP.

Ich bin für jeden Rat dankbar :K

Code: Alles auswählen

#!/usr/bin/env python
from werkzeug.wrappers import Request, Response
try:
    import sqlite3
except ImportError:
    from pysqlite2 import dbapi2 as sqlite3

import StringIO
import Image

@Request.application
def application(request):
            conn = sqlite3.connect("photo.db")
            sql = """SELECT image FROM photo LIMIT 1"""
            cur = conn.cursor()
            cur.execute(sql)
            fp = StringIO.StringIO(cur.fetchone()[0])
            bild = Image.open(fp)
            response = bild.tostring("png")
            return response

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4001, application)
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Der fehlte wohl beim Kompilieren von PIL die von PIL verwendete PNG-Library (ich vermute mal libpng). Installier die mal (im Zweifelsfall in der PIL-Doku nachschauen) und installiere PIL dann nochmal.
heinrich75
User
Beiträge: 7
Registriert: Donnerstag 10. Februar 2011, 15:03

Leider dürfte es nicht an der Libary liegen.
Ich habe die vorkompilierte Version entfernt und PIL direkt vom Source explizit mit PNG unterstützung kompiliert.

Leider bekomme ich dennoch die selbe Fehlermeldung :?
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Das Werkzeug-Skript neugestartet danach?
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
heinrich75
User
Beiträge: 7
Registriert: Donnerstag 10. Februar 2011, 15:03

Wie kann ich denn Werkzeug explizit neustarten?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Indem Du das Script, beendest und es neu aufrufst ;-)

Da wir hier im dunkeln tappen, ein paar Vorschläge:
  • Poste doch mal den vollständigen Traceback!
  • Simuliere das Laden des Bildes doch mal in einem separaten Script oder der Shell
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
heinrich75
User
Beiträge: 7
Registriert: Donnerstag 10. Februar 2011, 15:03

Ja, das habe ich natürlich gemacht ;-)

Anbei der gesamte Traceback.

Code: Alles auswählen

 * Running on http://localhost:4001/
127.0.0.1 - - [11/Feb/2011 09:18:56] "GET / HTTP/1.1" 500 -
Error on request:
Traceback (most recent call last):
  File "C:\Python26\lib\site-packages\werkzeug-0.6.2-py2.6.egg\werkzeug\serving.py", line 153, in run_wsgi
    execute(app)
  File "C:\Python26\lib\site-packages\werkzeug-0.6.2-py2.6.egg\werkzeug\serving.py", line 140, in execute
    application_iter = app(environ, start_response)
  File "C:\Python26\lib\site-packages\werkzeug-0.6.2-py2.6.egg\werkzeug\wrappers.py", line 245, in <lambda>
    return _patch_wrapper(f, lambda *a: f(*a[:-2]+(cls(a[-2]),))(*a[-2:]))
  File "C:\Dokumente und Einstellungen\heinrich\workspace\test\src\testserv.py", line 19, in application
    response = bild.tostring("png")
  File "C:\Python26\lib\site-packages\PIL\Image.py", line 535, in tostring
    e = _getencoder(self.mode, encoder_name, args)
  File "C:\Python26\lib\site-packages\PIL\Image.py", line 401, in _getencoder
    raise IOError("encoder %s not available" % encoder_name)
IOError: encoder png not available
  • Ich kann das Bild mit einem anderen Script laden und anzeigen.
  • Ich kann es auch aus der Datenbank auslesen, im Filesystem ablegen und vom Filesystem wieder lesen.
  • Nur direkt aus der Datenbank kann ich es nicht anzeigen lassen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

heinrich75 hat geschrieben:
  • Nur direkt aus der Datenbank kann ich es nicht anzeigen lassen.
Also der Fehler ist ja ganz eindeutig ein PIL-Fehler. Er kennt wohl "png" als Encoder nicht.

Und Du hast Dein separates Script auch auf derselben Maschine laufen lassen?

Und in dem kannst Du es auch nur aus einem File des Dateisystems laden und nicht per StringIO?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
heinrich75
User
Beiträge: 7
Registriert: Donnerstag 10. Februar 2011, 15:03

Ich habe PIL mit der beigepackten selftest.py überprüft

python selftest.py
--------------------------------------------------------------------
PIL 1.1.7 TEST SUMMARY
--------------------------------------------------------------------
Python modules loaded from .\PIL
Binary modules loaded from .\PIL
--------------------------------------------------------------------
--- PIL CORE support ok
*** TKINTER support not installed
*** JPEG support not installed
--- ZLIB (PNG/ZIP) support ok
*** FREETYPE2 support not installed
*** LITTLECMS support not installed
--------------------------------------------------------------------

Zusätzlich habe ich eine neue Maschine installiert, welche nur Betriebsystem, Python 2.6, werkzeug und PIL installiert hat, jedoch ohne Erfolg.

Ja, das Filesystem Script lauft auf der selben Maschine, jedoch funktioniert auch hier nur das Speichern des PNG. Beim Lesen scheitert er ebenfalls.

Gibt es abgesehen von PIL eine andere Möglichkeit das Bild aus der Datenbank an Werkzeug weiterzugeben?
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Eigentlich brauchst du ja PIL gar nicht dafür. Du willst ja keine Bilder bearbeiten. Nimm einfach die Daten aus der Datenbank und verwende sie direkt als Antwort.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dauerbaustelle hat geschrieben:Eigentlich brauchst du ja PIL gar nicht dafür. Du willst ja keine Bilder bearbeiten. Nimm einfach die Daten aus der Datenbank und verwende sie direkt als Antwort.
Als Lösung natürlich richtig. Dennoch ist es ja schon merkwürdig. Klingt für mich nach Bug. Speziell, da augenscheinlich das Speichern klappen soll und das Laden nicht...
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
heinrich75
User
Beiträge: 7
Registriert: Donnerstag 10. Februar 2011, 15:03

Mein Versuch ohne PIL, mit folgendem Code.

Code: Alles auswählen

#!/usr/bin/env python
from werkzeug.wrappers import Request, Response
try:
    import sqlite3
except ImportError:
    from pysqlite2 import dbapi2 as sqlite3

import StringIO
import Image

@Request.application
def application(request):
            conn = sqlite3.connect("osm.db")
            sql = """SELECT image FROM osm LIMIT 1"""
            cur = conn.cursor()
            cur.execute(sql)
            response = (cur.fetchone()[0])
            return response

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4001, application)
Erzeugt leider folgenden Trace.

Code: Alles auswählen

Traceback (most recent call last):
  File "C:\Python26\lib\site-packages\werkzeug-0.6.2-py2.6.egg\werkzeug\serving.py", line 153, in run_wsgi
    execute(app)
  File "C:\Python26\lib\site-packages\werkzeug-0.6.2-py2.6.egg\werkzeug\serving.py", line 140, in execute
    application_iter = app(environ, start_response)
  File "C:\Python26\lib\site-packages\werkzeug-0.6.2-py2.6.egg\werkzeug\wrappers.py", line 245, in <lambda>
    return _patch_wrapper(f, lambda *a: f(*a[:-2]+(cls(a[-2]),))(*a[-2:]))
TypeError: 'buffer' object is not callable
Ich vermute auch einen Bug, ich habe jedoch keinen "aktuellen" Sourcecode von PIL gefunden. Habe daher die letzte Stabile Version 1.1.7 ist von 2009 verwendet.
Dauerbaustelle
User
Beiträge: 996
Registriert: Mittwoch 9. Januar 2008, 13:48

Muss man da nicht ein Response-Objekt zurückgeben? Ich würde mir vielleicht für so einfache Webanwendungen mal Flask anschauen.
heinrich75
User
Beiträge: 7
Registriert: Donnerstag 10. Februar 2011, 15:03

Danke für die zahlreichen Antworten, das Response Objekt war der entscheidende Hinweis ;-)

Folgender Code funktioniert

Code: Alles auswählen

#!/usr/bin/env python
from werkzeug.wrappers import Request, Response
try:
    import sqlite3
except ImportError:
    from pysqlite2 import dbapi2 as sqlite3

import StringIO
import Image

@Request.application
def application(request):
            conn = sqlite3.connect("osm.db")
            sql = """SELECT image FROM osm LIMIT 1"""
            cur = conn.cursor()
            cur.execute(sql)
            response = Response()
            response.data = (cur.fetchone()[0])
            response.headers['Content-Type'] = 'image/png'
            return response

if __name__ == '__main__':
    from werkzeug.serving import run_simple
    run_simple('localhost', 4001, application)
Antworten