UnicodeEncodeError

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
nvidia
User
Beiträge: 31
Registriert: Freitag 11. Februar 2011, 16:46

Hallo ich hab ein Problem,
ich hab folgenden string:
=?ISO-8859-1?Q?TOP_RISIKO-Lebensversicherung_=96_jetzt_g=FCnstig_sichern?=
jage den durch folgende Methode:

Code: Alles auswählen

	def _back2unicode(self, s, default = 'iso-8859-15'):
		for txt, char in email.header.decode_header(s):
			try:
				s = unicode(txt, char or 'ascii', 'strict')
			except:
				s = txt.decode(default, 'ignore')
			finally:
				return u'{0}'.format(s)
Also Ergebnis erhalte ich:
u'Top Risiko-Lebensversicherung \x96 jetzt g\xfcnstig sichern'
und wenn ich den jetzt über print ausgebe krieg ich den Fehler:
UnicodeEncodeError: 'charmap' codec can't encode character u'\x96' in position 30: character maps to <undefined>
in einer internen Methode >> return codecs.charmap_encode(input,errors,encoding_map)
Woher kommt der Fehler? Wie behebe ich ihn?
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

nvidia hat geschrieben: ich hab folgenden string:
=?ISO-8859-1?Q?TOP_RISIKO-Lebensversicherung_=96_jetzt_g=FCnstig_sichern?=
Das ist doch keine `repr`-Ausgabe!?! Woher kommt denn der String? Wie kommst Du auf diese Darstellung?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
nvidia
User
Beiträge: 31
Registriert: Freitag 11. Februar 2011, 16:46

Das ist ein Q-encoded string für den versand von emails.
Und diese Methode soll sie wieder umwandeln.
Den string hab ich von einem realen email-betreff.
Was ist 'repr'?
Also bei den anderen Emails in meinem Postfach lief das normal auch in der Console werden üäös richtig angezeigt.
Ich weiß nur nicht genau, wieso das hier nicht klappt.
// Also ich das nochmal schritt per schritt mit der hand durchgeganngen
header.decode liefert
schon den string den man am Ende sieht.
Nach unicode() sollte jetzt die ganzen \x-zeichen verschwinden.
Das tun sie aber nicht => a) die Methode funktioniert nicht richtig b) der String war von anfang an fehlerhaft
nvidia
User
Beiträge: 31
Registriert: Freitag 11. Februar 2011, 16:46

pfff hab endlich die Lösung.
Man kann das Zeichen nicht anzeigen, sie existieren aber.
Deswegen wirft unicode keine Fehlermeldung, aber print.
aus wiki:
Den Positionen 00–1F und 7F–9F sind in ISO/IEC 8859 und damit ISO/IEC 8859-1 keine Zeichen zugewiesen. ISO-8859-1 jedoch besetzt alle diese Stellen mit nicht darstellbaren Steuerzeichen.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Da Deine for-Schleife ja eh nach der ersten Zeile abbricht, wieso machst Du das nicht einfach so und nimmst direkt das erste Tupel?

Code: Alles auswählen

In [29]: msg, encoding = email.header.decode_header(qenc)[0]

In [30]: msg.decode(encoding)
Out[30]: u'TOP RISIKO-Lebensversicherung \x96 jetzt g\xfcnstig sichern'

In [31]: print msg.decode(encoding)
TOP RISIKO-Lebensversicherung  jetzt günstig sichern
Dein finally ist auf jeden Fall komplizierter als notwendig, da Du `s` einfach auch so zurückgeben könntest - das ist ja da schon ein unicode-Objekt ;-)

Sollte es nicht immer ein Encoding geben, so hast Du ja ein default-Encoding - wozu die Verrenkung mit "ascii"?

Desweiteren sieht der Code inkonsistent aus - wieso nutzt Du nicht beide Male die `str.decode`-Methode?

Es ist idR. unschön, wenn man an einen Namen unterschiedliche Typen bindet, zudem ist `s` recht kryptisch. Wie wäre es mit `message` oder `msg` und dann `decoded_message` oder `dec_msg`? Oder Du nimmst direkteren Bezug und nennst es sogar `qencoded` und `qdecoded`; je nach Gusto noch mit `_message` oder `_msg` Suffix.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
nvidia
User
Beiträge: 31
Registriert: Freitag 11. Februar 2011, 16:46

okay danke, jetzt sieht das um einiges lesbarer aus.
Wie hast du das geschafft, dass das \x96 verschwindet in der letzten Ausgabe?
Ich krieg da immer noch den Error
nomnom
User
Beiträge: 487
Registriert: Mittwoch 19. Mai 2010, 16:25

nvidia hat geschrieben:okay danke, jetzt sieht das um einiges lesbarer aus.
Wie hast du das geschafft, dass das \x96 verschwindet in der letzten Ausgabe?
Ich krieg da immer noch den Error
Du verwendest vermutlich Windows und die Windows Shell und die benutzt dieses cp850-Encoding und das wirft da immer diese Fehler bei nicht-Unicode-Strings. Wie man das beheben kann weiß ich auch nicht.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

nomnom hat geschrieben: Du verwendest vermutlich Windows und die Windows Shell und die benutzt dieses cp850-Encoding und das wirft da immer diese Fehler bei nicht-Unicode-Strings. Wie man das beheben kann weiß ich auch nicht.
Nein, bitte nicht Dinge vermischen! Auf eine Shell werden immer kodierte Bytes gesendet. Bei mir werden die in UTF-8 umgewandelt, welches Umlaute darstellen kann.

Code: Alles auswählen

In [3]: sys.getfilesystemencoding()
Out[3]: 'UTF-8'
Dieses Encoding muss eben in Shell und sys-Modul übereinstimmen, dann kann man print mit Unicode-Objekten bedenkenlos benutzen (Python 2.x).

Ansonsten muss man sie explizit entsprechend encodieren:

Code: Alles auswählen

print unicode_obj.encode(sys.getfilesystemencoding())
Wie immer empfehle ich einen Blick in meine Sig :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
nvidia
User
Beiträge: 31
Registriert: Freitag 11. Februar 2011, 16:46

ahhh, wieder was gelernt.
Mein encoding ist 'mbcs' .
Mit deiner Methode kann man das ausgeben.
Da krieg ich für den nichtdef. u'\x96' ein Fragezeichen ;-)
Antworten