UnicodeDecodeError bei Formularauswertung

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.
Antworten
0815pascal
User
Beiträge: 7
Registriert: Montag 26. Januar 2009, 15:28

Hallo miteinander, bin Python-Neuling und spiele gerade ein wenig damit rum. Ich will per Formular eine Wert weitergeben, der nacher ausgegeben werden soll. Dann bekomm ich allerdings die Fehlermeldung
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 7: ordinal not in range(128)
Der Code ist

Code: Alles auswählen

class checkAnswer(webapp.RequestHandler):
    def post(self):
        greeting = Greeting()
        usersolution = self.request.get('usersolution')
        self.response.out.write('''<html><body>''')
        self.response.out.write('''Deine Lösung ist %s''' %usersolution)
ich arbeite übrigens mit Google AppEngine, falls sich jmd. über webapp.RequestHandler wundern sollte.

Das PY-Dokument hab' ich als UTF-8 kodiert abgespeichert. Verstehe drum die Fehlermeldung nicht so ganz...
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Da gibt es einen netten Wiki Artikel zu: [wiki]Von Umlauten, Unicode und Encodings[/wiki]
0815pascal
User
Beiträge: 7
Registriert: Montag 26. Januar 2009, 15:28

ich kenn' den Artikel bereits, aber versteh' nicht wirklich, was ich machen soll, bzw. was das problem ist.
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

Dein Code stolpert über das 'ö' in Lösung. Wahrscheinlich versucht die write-Methode den nach UTF8 zu bringen, vergleichbar mit:

Code: Alles auswählen

"Deine Lösung".encode("utf-8")
Das geht schief, weil er vor dem Encoden versuchen muss, das ganze nach Unicode zu bringen - also den String erstmal zu dekodieren. Standardmäßig nimmt Python an, dass der String ein Ascii-String ist. Und weil's in Ascii kein ö gibt, gibt's eben die Exception.

Wahrscheinlich genügt es, wenn du einfach folgendes machst:

Code: Alles auswählen

class checkAnswer(webapp.RequestHandler):
    def post(self):
        greeting = Greeting()
        usersolution = self.request.get('usersolution')
        self.response.out.write('''<html><body>''')
        self.response.out.write(u'''Deine Lösung ist %s''' %usersolution)
Da du oben in deiner Python-Datei das Encoding, in dem die Datei geschrieben wurde, angegeben haben solltest, dekodiert Python es richtig und übergibt der write-Methode ein Unicode-Objekt, mit der es keine weiteren Probleme geben sollte.

Gruß,
Manuel
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

Das PY-Dokument hab' ich als UTF-8 kodiert abgespeichert. Verstehe drum die Fehlermeldung nicht so ganz.
..

Die utf-8 Codierung bewirkt nur, dass Dein Editor den Quelltext im utf-8 Format abspeichert. Vor dem write-Aufruf musst Du den zu versendenen String als utf-8 encoden; schematisch:

Code: Alles auswählen

s = "Lösung".encode('utf8')
write(s)
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

kbr hat geschrieben:
Das PY-Dokument hab' ich als UTF-8 kodiert abgespeichert. Verstehe drum die Fehlermeldung nicht so ganz.
..

Die utf-8 Codierung bewirkt nur, dass Dein Editor den Quelltext im utf-8 Format abspeichert. Vor dem write-Aufruf musst Du den zu versendenen String als utf-8 encoden; schematisch:

Code: Alles auswählen

s = "Lösung".encode('utf8')
write(s)
Das hilft aber noch nichts bei irgend welchen User-Eingaben! Die muss er ja vorher in Unicode decodieren ...

Generell gilt wie immer:
So früh wie möglich in Unicode wandeln und so spät wie möglich in einen Codec wandeln (und Nein, Unicode ist nicht uft-8 o.ä. - es hat bei mir auch lange gedauert, das zu kapieren :-D )

Also hier wäre es sinnvoll, die Usereingabe direkt zu decodieren und dann wie gezeigt später in z-b- utf-8 zu wandeln, bevor man etwas schreibt!
Benutzeravatar
kbr
User
Beiträge: 1487
Registriert: Mittwoch 15. Oktober 2008, 09:27

hyperion hat geschrieben:Das hilft aber noch nichts bei irgend welchen User-Eingaben! Die muss er ja vorher in Unicode decodieren ...
Wenngleich es ursprünglich erst einmal um die Ausgabe ging, ist das natürlich korrekt; wobei beim decoden des Inputs wiederum das encoding des Formulars bekannt sein sollte ... genug der Verwirrung :)
0815pascal
User
Beiträge: 7
Registriert: Montag 26. Januar 2009, 15:28

hmm wenn ich

Code: Alles auswählen

u'''Deine Lösung ist"
schreibe, klappt halbwegs. Allerdings gibt es dann "Deine Lösung ist" aus. Das ö wird nicht richtig angezeigt

Versuche ich es mit

Code: Alles auswählen

s= "Lösung".encode('utf8')
write(s)
bekomme ich wieder die Meldung

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Weil man Bytestrings nicht enkodieren sondern eigentlich nur dekodieren kann (wenn du einen Bytestring enkodierst, wird er in Unicode mit dem Charset ASCII dekodiert und dann mit deinem gewünschten Charset dekodiert, was wegen dem ASCII eben fehlschlägt).
tordmor
User
Beiträge: 100
Registriert: Donnerstag 20. November 2008, 10:29
Wohnort: Stuttgart

Der Fehler ist ein Decode-Error. Das bedeutet es wird versucht Binärdaten in unicode umzuwandeln. Das geschieht offensichtlich in self.response.out.write. Du übergibst ein Bytestring im ursprünglichen Code. Bytestrings werden unabhängig der codierung des Quelltextes versucht als ASCII zu decodieren, was fehlschlägt, da Umlaute in Ascii nicht definiert sind. Wenn Du keinen Bytestring sondern ein Unicodestring übergibst (später mit u""), klappt alles. Die fehlerhafte Anzeige im letzten Fall kommt daher, dass zwar der Unicodestring von Googleapps als utf-8 codiert wird, aber Dein Browser davon nichts mitbekommt. Das kannst Du ändern, indem du einen Content-Type header setzt (Content-Type: text/html; charset=utf-8), oder eine entsprechende meta-Angabe in den header der html-Datei setzt.
http://www.felix-benner.com
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

Etwas mittels der u"..." in Unicode zu verwandeln klappt nur dann, wenn du das Encoding des Python Modules korrekt im Coding "Magic Comment" angegeben hast oder Python richtig geraten hat. Einfach deswegen, weil jeder String nunmal in der Datei in deren Encoding steht und dann mithilfe von u"..." in Unicode verwandelt werden würde beim Start des Interpreters. Unicode bekommt man nunmal nicht magisch.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Ich muß zugeben, daß ich die Codiererei auch noch nicht so ganz durchschaut habe. Hatte neulich schon so ein Problem bei einer Lösung von Rebecca. Ich habe mal so was probiert.

Code: Alles auswählen

print "L"+u"\xF6"+"sung"
Vielleicht hilfts.

Jedenfalls interessant.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Mit Wiki und PEP-263 habe ich jetzt noch folgende Variante gefunden, die unabhängig vom Editor sein sollte:

Code: Alles auswählen

# coding=iso-8859-1
print "Lösung".decode("iso-8859-1")
Zuletzt geändert von hendrikS am Montag 26. Januar 2009, 23:28, insgesamt 1-mal geändert.
BlackJack

Man kann u'L\xf6sung' aber auch echt umständlich schreiben. :-)

Edit: Nein das ist nicht unabhängig vom Editor. Der muss das nämlich auch noch in der angegebenen Kodierung speichern können.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

@BlackJack:
Danke für den Tip, wie man den String einfach aufschreibt.

Hinsichtlich Editor habe ich eben nochmal bei PEP-263 geguckt. Das sollte unabhängig vom Editor sein. Es gibt zwei Methoden:
1.)

Code: Alles auswählen

#coding=<encoding name>
2.)

Code: Alles auswählen

# -*- coding: <encoding name> -*-
So wie ich es verstanden habe, ist nur die zweite vom Editor abhängig. Aber vielleicht irre ich mich auch.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Nein, das ist einfach nur die Vim* oder die Emacs-Syntax für die Angabe des Encodings, die auch vom Python-Interpreter ausgewertet werden kann.

* Jetzt davon mal abgesehen, dass Vim meistens die Modelines sowieso nicht auswertet.
Benutzeravatar
helduel
User
Beiträge: 300
Registriert: Montag 23. Juli 2007, 14:05
Wohnort: Laupheim

hendrikS hat geschrieben:Hinsichtlich Editor habe ich eben nochmal bei PEP-263 geguckt. Das sollte unabhängig vom Editor sein. Es gibt zwei Methoden:
Eigentlich gibt es Methoden wie Sand am Meer. Auch das funktioniert:

Code: Alles auswählen

#lsdkfjsdlkfjslfjkdljkfdksfdjsdlfkjcoding: utf-8 lsdkjflsdkjflsdkfj
:lol:
Es ist völlig Wurst, was in der Zeile steht, wichtig ist nur, dass in einer der ersten beiden Zeilen im Kommentar "coding: <coding>" steht. Alles andere drumherum ist egal.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Ich habe den Eindruck, dass hendrikS nicht verstanden hat, dass zusätzlich zur Encoding-Angabe die Datei vom Editor eben noch in dem dort angegebenen Format gespeichert werden muss. Es nützt rein gar nichts da utf-8 reinzuschreiben, die Datei dann aber als ASCII zu speichern.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Es ist völlig Wurst, was in der Zeile steht, wichtig ist nur, dass in einer der ersten beiden Zeilen im Kommentar "coding: <coding>" steht. Alles andere drumherum ist egal.[/quote]

Ja und Nein:

Das Drumherum ist egal sonst gibt es aber zwei Möglichkeiten der Zuweisung:
#coding: <coding>
#coding = <coding>

So geschrieben in PEP-263. Und geht auch so.

Langsam kommt jetzt bei mir hier etwas Licht ins Dunkel.
Auch, dass ich explizit im UTF-8 format speichern muss sofern UTF-8 Kodierung verwendet wird, wie schon einige hier angemerkt haben. Mein Editor unterstuetzt das Feature leider nicht.
Ist mir jetzt auch klar warum ich Rebeccas code aus einem anderen Thread neulich nicht sofort zum Laufen gebracht habe. Habe diesen jetzt mal im emacs kopiert und gespeichert. Läuft.
Wieder was gelernt. :D
Antworten