CherryPy, SQLite, Zeichenkodierung

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Benutzeravatar
encbladexp
User
Beiträge: 61
Registriert: Freitag 7. März 2003, 19:28
Kontaktdaten:

CherryPy, SQLite, Zeichenkodierung

Beitragvon encbladexp » Montag 24. Dezember 2007, 23:24

Tag Leute,

nachdem ich es jetzt 2 Stunden mit Error-And-Trial sowie dem guten alten google versucht habe, hiermal ein Problem, welches bestimmt blos eine Kleinigkeit ist :-( , aber ich seh den Wald vor lauter Bäumen irgendwie nicht mehr... :oops:

Problem:
Meine CherryPy Anwendung liefert alle Seiten als UTF-8 aus, das ist auch so gewollt und per Content-Type so eingestellt.

Nun bekommt der Client ein Formular, alles funktioniert wie es soll, aber:
Wenn ein Umlaut, bzw. nicht ASCII-Zeichen in einem Textfeld vorkommt, wird dies bei der Anzeige falsch dargestellt, also z.B. in der Quelltextansicht als dieses ?-Zeichen mit der Box außen rum. Ich vermute er kann das Zeichen irgendwo nicht finden.

Diagnose:
Ich habe die betroffene Seite mal mit wget/curl runtergeladen, und mit vim angesehen -> Filetype ist ISO-8859-1, sollte aber UTF-8 sein. Auch file auf der Konsole bestätigt das, mit ":set fileencoding=utf-8" kann ich die Datei auch nach UTF-8 umwandeln, under Browser zeigt diese dann auch richtig an.

Vermutung:
Meine Datenbankabfrage schiebt die Daten per cursor.execute() direkt in die Datenbank, also so wie es vom Client kommt, natürlich mit Escaping wegen SQL-Injection und co, aber sonst wird nix gemacht.

Bei der Ausgabe wird nicht konvertiert, und so kommt der ISO-8859-1 Bytestring in den Unicode Output der zum Browser geht, und peng haben wir mein Problem.

Aber: Wie Löse ich das Problem? Ich glaube zu wissen woran es liegt, aber ich finde beim besten willen keine Lösung, was ich schon versucht habe:

string.encode("utf-8") -> UnicodeDecodeError (der Klassiker, wenn es um Kodierungen geht)
Content-Type auf ISO-8859-1 -> Betroffener Text ist nun richtig, aber halt dafür der UTF-8 Teil falsch *arg*

Am liebsten wäre es mir wenn ich die Daten direkt als "richtiges" UTF-8 in der Datenbank hätte, dann hätte alles (Templates, Content-Type usw...) UTF-8, und ich muss nur einmal konvertieren, und nicht bei jeder Page-Impression...

mfg Betz Stefan
PS: Hoffentlich konnte mir jetzt dabei jemand folgen....
PPS: Die entsprechenden Code-Teile könnte ich liefern wenn benötigt!
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Re: CherryPy, SQLite, Zeichenkodierung

Beitragvon Leonidas » Montag 24. Dezember 2007, 23:36

stefan_betz hat geschrieben:Nun bekommt der Client ein Formular, alles funktioniert wie es soll, aber:
Wenn ein Umlaut, bzw. nicht ASCII-Zeichen in einem Textfeld vorkommt, wird dies bei der Anzeige falsch dargestellt, also z.B. in der Quelltextansicht als dieses ?-Zeichen mit der Box außen rum. Ich vermute er kann das Zeichen irgendwo nicht finden.

Nein, es gibt so ein Zeichen in deinem Font nicht. Was darauf hinweist, dass da, wenn es einen Font gäbe der das darstellt sowieso nur Quark stehen würde.

Naja, die Lösung ist ganz einfach: dem User Agent sagen er soll alles was er hochlädt UTF-8 kodieren, so dass auf dem Server ein UTF-8 Bytestring ankommt. Den tust du in Unicode decoden (das das bei dir ein Fehler kommt liegt daran dass der Bytestring eben nicht UTF-8 kodiert ist sondern in etwas anderem) und dann in deinem Programm verarbeiten. Wenn du die Sachen in die Datenbank schreibst musst du mal gucken, ob es funktioniert direkt Unicode-Daten dort abzusetzen oder ob du sie erstmal in UTF-8 enkodieren musst.
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

Beitragvon mitsuhiko » Montag 24. Dezember 2007, 23:41

Dekodiert CherryPy automatisch eingehende Daten? Wenn nicht musst du das noch selber machen.
TUFKAB – the user formerly known as blackbird
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Dienstag 25. Dezember 2007, 01:30

Hallo Stefan!

1.) Liefere alles als UTF-8 aus
2.) Nimm an, dass du darauf hin auch wieder UTF-8 vom Browser bekommst
3.) Stelle CherryPy so ein, dass es UTF-8 ausliefert, wenn Unicode im Spiel ist.
4.) Stelle CherryPy so ein, dass es UTF-8 automatisch nach Unicode umwandelt, wenn es Daten vom Browser bekommt.

In den Kopf der (X)HTML-Datei:

Code: Alles auswählen

  <meta http-equiv="content-type" content="text/html; charset=utf-8" />


In die INI-Datei:
[code=][/]
tools.encode.on = True
tools.encode.encoding = "utf-8"
tools.decode.on = True[/code]

Und jetzt musst du nur noch darauf achten, dass von CherryPy Unicode oder (wenn schon Bytestring, dann) UTF-8 ausgeliefert wird.

In die SQLite-Datenbank immer nur Unicode oder UTF-8-Bytestrings speichern. Unicode wird automatisch nach UTF-8 umgewandelt, da das das vordefinierte Textencoding von SQLite ist. Und wenn du Text aus der SQLite-Datenbank ausliest, dann bekommst du Unicode zurück.

Siehe: http://www.python-forum.de/topic-6654.html

Halte mich am Laufenden, ob es funktioniert hat.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
encbladexp
User
Beiträge: 61
Registriert: Freitag 7. März 2003, 19:28
Kontaktdaten:

Beitragvon encbladexp » Dienstag 25. Dezember 2007, 02:05

gerold hat geschrieben:1.) Liefere alles als UTF-8 aus


Wird schon gemacht.

gerold hat geschrieben:2.) Nimm an, dass du darauf hin auch wieder UTF-8 vom Browser bekommst


Schön wärs :-)

gerold hat geschrieben:In den Kopf der (X)HTML-Datei:


Sollte eigentlich nicht nötig sein, da CherryPy ja schon den korrekten Header ausliefert, ich habs testweise aber dennoch mit rein, man weis ja nie.

gerald hat geschrieben:In die INI-Datei:


Kommt ein UnicodeDecodeError beim Ausliefern der Logon-Page...

Einfache Lösung wäre natürlich wenn man den Browser "zwingen" könnte UTF-8 auszuliefern, aber nur wie?

Aber was mir noch auffällt, beim UnicodeDecodeError kommt immer das der ascii Codec XYZ nicht kann, wo stellt man nochmal das Default Encoding ein? Das könnte auch das Problem der 3 INI-Zeilen von dir lösen...

mfg Betz Stefan
PS: Die Python Datei, wo aktuell auch noch die Templates drin sind hat auch coding: utf-8...[/code]
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5554
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Telfs (Tirol)
Kontaktdaten:

Beitragvon gerold » Dienstag 25. Dezember 2007, 11:54

Hallo Stefan!

Wenn du intern nicht mit Unicode, sondern mit UTF-8 arbeitest, dann darfst du ``tools.decode.on = True`` nicht einschalten.

Das sieht dann so aus:
- cpexample.ini: http://paste.pocoo.org/show/17540/
- cpexample.py: http://paste.pocoo.org/show/17541/

Wenn du intern *mit Unicode* arbeitest, dann musst du ``tools.decode.on = True`` aktivieren. Damit wird das was du vom Browser zurück bekommst automatisch nach Unicode umgewandelt.

Achte darauf, dass der Vorlagentext im Beispiel jetzt Unicode ist. Das sieht dann so aus:
- cpexample.ini: http://paste.pocoo.org/show/17542/
- cpexample.py: http://paste.pocoo.org/show/17543/

Und falls du Cheetah als Vorlagensprache verwendest, musst du entweder ``#encoding utf-8`` oder ``#unicode utf-8`` setzen. Je nachdem ob du Unicode oder Bytecode von der Vorlage zurück bekommen möchtest.
Und so sieht das Beispiel aus, wenn du intern mit Unicode arbeitest:
- cpexample.ini: http://paste.pocoo.org/show/17542/
- cpexample.py: http://paste.pocoo.org/show/17544/
- cpexample.tmpl: http://paste.pocoo.org/show/17545/

Achte darauf, dass in der Cheetah-Vorlage ganz oben ``#unicode utf-8`` steht. Diese Anweisung kümmert sich darum, dass die Vorlage automatisch von utf-8 nach Unicode umgewandelt wird. Das ist noch ziemlich neu (seit Version 2.0rc8)

Halte mich bitte wieder am Laufenden.

mfg
Gerold
:-)

PS: Beim Testen dieser Beispiele hinter dem Apachen (mit mod_fastcgi) hat mir der Apache kurz einen Streich gespielt. Ich hatte unvorsichtigerweise in der ``apache2.conf`` die Einstellung ``AddDefaultCharset On`` gesetzt. Das bewirkt dass der Apache alles als "iso-8859-1" ausliefert. Nach dem Auskommentieren dieser Einstellung lief alles wie erwartet. :D
http://halvar.at | Kleiner Bascom AVR Kurs

Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
encbladexp
User
Beiträge: 61
Registriert: Freitag 7. März 2003, 19:28
Kontaktdaten:

Beitragvon encbladexp » Dienstag 25. Dezember 2007, 12:41

Problem ist jetzt gelöst, und zwar hatten meine ganzen Internen String kein u vor dem String, waren also normale Bytestrings. Dadurch konnte das mit dem tools.encode & co ja nicht gehen, deswegen kam auch der Fehler.

Mit deinen 3 Zeilen in der .ini, und dem u vor den Strings in meinen Sourcen geht es jetzt einwandfrei.

Danke nochmal für die Hilfe

mfg Betz Stefan :lol:

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder