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

Montag 26. Januar 2009, 15:35

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: 2450
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Montag 26. Januar 2009, 15:41

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

Montag 26. Januar 2009, 16:43

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

Montag 26. Januar 2009, 17:22

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: 870
Registriert: Mittwoch 15. Oktober 2008, 09:27

Montag 26. Januar 2009, 17:25

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: 7472
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Montag 26. Januar 2009, 17:56

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: 870
Registriert: Mittwoch 15. Oktober 2008, 09:27

Montag 26. Januar 2009, 18:23

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

Montag 26. Januar 2009, 19:38

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
Administrator
Beiträge: 16024
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Montag 26. Januar 2009, 19:51

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

Montag 26. Januar 2009, 20:27

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

Montag 26. Januar 2009, 20:46

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

Montag 26. Januar 2009, 22:44

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

Montag 26. Januar 2009, 23:28

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

Montag 26. Januar 2009, 23:28

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

Montag 26. Januar 2009, 23:41

@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.
Antworten