2010-07-11 8 views
14

Mögliche Duplizieren:
Python UnicodeDecodeError - Am I misunderstanding encode?Python: Sanitize eine Zeichenfolge für Unicode?

Ich habe eine Zeichenfolge, die ich versuche, sicher für die unicode() Funktion zu machen:

>>> s = " foo “bar bar ” weasel" 
>>> s.encode('utf-8', 'ignore') 

Traceback (most recent call last): 
    File "<pyshell#8>", line 1, in <module> 
    s.encode('utf-8', 'ignore') 
UnicodeDecodeError: 'ascii' codec can't decode byte 0x93 in position 5: ordinal not in range(128) 
>>> unicode(s) 

Traceback (most recent call last): 
    File "<pyshell#9>", line 1, in <module> 
    unicode(s) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0x93 in position 5: ordinal not in range(128) 

ich meistens bin flailing um Hier. Was muss ich tun, um die unsicheren Zeichen aus der Zeichenfolge zu entfernen?

Etwas zu diesen question Zusammenhang, auch wenn ich nicht in der Lage war mein Problem von ihm zu lösen.

Dies scheitert auch:

>>> s 
' foo \x93bar bar \x94 weasel' 
>>> s.decode('utf-8') 

Traceback (most recent call last): 
    File "<pyshell#13>", line 1, in <module> 
    s.decode('utf-8') 
    File "C:\Python25\254\lib\encodings\utf_8.py", line 16, in decode 
    return codecs.utf_8_decode(input, errors, True) 
UnicodeDecodeError: 'utf8' codec can't decode byte 0x93 in position 5: unexpected code byte 
+0

Ich frage mich, warum 'str' überhaupt eine' encode'-Funktion hat und ob der Parameter "encoding" die Kodierung des Ergebnisses oder die Kodierung des Eingangs angibt. Was genau versuchst du hier zu machen? – Thanatos

+0

Bitte überprüfen Sie [this] (http://stackoverflow.com/questions/368805/python-unicodedecodeerror-am-i-misunderstanding-encode/370199#370199) Antwort auf eine verwandte Frage: "Python UnicodeDecodeError - bin ich Missverständnis Encode? " – tzot

+0

Für diejenigen, die nach einer Lösung suchen, um Unicode-Sonderzeichen in (X) HTML zu bereinigen, versuchen Sie' u'my unicode str'.encode ('ascii', 'xmlcharrefreplace') '. – toszter

Antwort

4

EDIT. Sieht aus wie die Zeichenfolge so codiert ist, dass (LEFT DOUBLE ANFÜHRUNGSZEICHEN) wird \x93 und (RIGHT DOUBLE ANFÜHRUNGSZEICHEN) wird \x94. Es gibt eine Reihe von Codepages mit einer solchen Zuordnung ist CP1250 einer von ihnen, so dass Sie diese verwenden:

s = s.decode('cp1250') 

Für alle Codepages, die Karte zu \x93 sehen here (alle von ihnen auch zu \x94 Karte , die verifiziert werden können here).

+0

Dieser Anruf scheitert für mich (siehe oben) –

+0

@Rosarch OK, jetzt sehe ich die ursprüngliche Zeichenfolge. Ich habe die Antwort aktualisiert (und in der Zwischenzeit hatte @darkporter die gleiche Lösung gefunden). – Bolo

+0

Nice Link auf den Code-Seiten. Es sieht so aus, als wären sie alle Variationen von "Windows". Wenn Sie "Western" sind, würde ich sagen, bleiben Sie einfach bei 1252. – jpsimons

37

Gute Frage. Codierungsprobleme sind schwierig. Beginnen wir mit "Ich habe eine Zeichenfolge." Strings in Python 2 sind nicht wirklich "Strings", sind sie Byte-Arrays. Also deine Zeichenkette, woher kam sie und in welcher Kodierung ist sie? Ihr Beispiel zeigt geschweifte Anführungszeichen im Literal, und ich bin mir nicht einmal sicher, wie Sie das gemacht haben. Ich versuche, es in einen Python-Interpreter einzufügen, oder tippe es unter OS X mit Option- [, und es kommt nicht durch.

Wenn Sie Ihr zweites Beispiel betrachten, haben Sie ein Zeichen von Hex 93. Das kann nicht UTF-8 sein, weil in UTF-8 jedes Byte höher als 127 Teil einer Multibyte-Sequenz ist. Also ich vermute, dass es Latin-1 sein soll. Das Problem ist, dass x93 kein Zeichen im Zeichensatz Latin-1 ist. Es gibt diesen "ungültigen" Bereich in Latin-1 von x7f bis x9f, der als illegal gilt. Microsoft sah jedoch diese ungenutzte Reichweite und entschied sich, "geschweifte Zitate" dort einzutragen. Dabei haben sie diese ähnliche Kodierung namens "windows-1252" erstellt, die wie Latin-1 ist, mit Inhalten in diesem ungültigen Bereich.

Also nehmen wir an, es ist Windows-1252. Was jetzt? String.decode konvertiert Bytes in Unicode, das ist also das, was Sie wollen. Ihr zweites Beispiel war auf der richtigen Spur, aber es ist fehlgeschlagen, weil die Zeichenfolge nicht UTF-8 war. Versuchen Sie:

>>> uni = 'foo \x93bar bar\x94 weasel'.decode("windows-1252") 
u'foo \u201cbar bar\u201d weasel' 
>>> print uni 
foo “bar bar” weasel 
>>> type(uni) 
<type 'unicode'> 

Das ist richtig, weil öffnendes geschweiftes Zitat Unicode U + 201C ist. Nun, da Sie Unicode haben, können Sie es an Bytes in jeder Codierung serialisiert Sie wählen (wenn Sie es über den Draht passieren müssen) oder nur als Unicode halten, wenn es in Python zu bleiben. Wenn Sie in UTF-8 konvertieren möchten, verwenden Sie die Funktion oppose, string.encode.

Curly Zitate nehmen 3 Bytes in UTF-8 zu kodieren. Sie könnten UTF-16 verwenden und sie wären nur zwei Bytes. Sie können jedoch nicht als ASCII oder Latin-1 kodieren, da diese keine Anführungszeichen haben.

+1

+1, aber Sie sollten auch erwähnen, dass diese Antwort spezifisch für Python 2.x ist. In 3.x wird der Typ "str" ​​in "bytes" umbenannt und "unicode" wird in "str" ​​umbenannt. Obwohl diese Änderung zunächst verwirrend ist, ist es weniger wahrscheinlich, dass dies geschieht. –

+0

+1 für "Lass uns mit 'Ich habe eine Zeichenfolge' beginnen" haha ​​ –

+1

@Daniel Nicht inzestuös zu sein, aber ich habe einfach deine Erklärung zur Abstimmung gewählt. Es ist wahr: das obige ist Python 2.x spezifisch. – jpsimons

Verwandte Themen