2016-07-01 9 views
14

Dies ist eine Folge zu Converting to Emoji. In dieser Frage hatte das OP eine json.dumps() -codierte Datei mit einem Emoji, das als Ersatzpaar dargestellt wurde - \ud83d\ude4f. Er/sie hatte Probleme beim Lesen der Datei und Übersetzen der Emoji richtig, und die korrekte war json.loads() jede Zeile aus der Datei, und die json Modul würde die Konvertierung von Ersatzpaar zurück zu (ich nehme an, UTF8-codiert) Emoji.Wie mit Ersatzpaaren in Python arbeiten?

So, hier ist meine Situation: sagen, ich habe nur ein ganz normales Python 3 Unicode-String mit einem Ersatzpaar in ihm:

emoji = "This is \ud83d\ude4f, an emoji." 

Wie verarbeiten ich diese Zeichenfolge eine Darstellung der emoji aus ihn heraus zu bekommen ? Ich suche so etwas zu bekommen:

"This is , an emoji." 
# or 
"This is \U0001f64f, an emoji." 

Ich habe versucht:

print(emoji) 
print(emoji.encode("utf-8")) # also tried "ascii", "utf-16", and "utf-16-le" 
json.loads(emoji) # and `.encode()` with various codecs 

Im Allgemeinen Ich erhalte eine Fehlermeldung ähnlich UnicodeEncodeError: XXX codec can't encode character '\ud83d' in position 8: surrogates no allowed.

Ich benutze Python 3.5.1 unter Linux, mit $LANG auf . Ich habe diese Beispiele sowohl im Python-Interpreter auf der Kommandozeile als auch in IPython in Sublime Text ausgeführt - es scheint keine Unterschiede zu geben.

Antwort

21

Sie haben eine Zeichenkette \ud83d in einer JSON-Datei auf der Festplatte (sechs Zeichen: \ u d 8 3 d) gemischt und eine Einzel Charakter u'\ud83d' (spezifiziert einen String mit wörtlichen in Python Quellcode) im Speicher. Es ist der Unterschied zwischen len(r'\ud83d') == 6 und len('\ud83d') == 1 auf Python 3.

Wenn Sie '\ud83d\ude4f' Python-String (Zeichen) sehen dann ein Fehler stromaufwärts ist. Normalerweise sollten Sie eine solche Zeichenfolge nicht erhalten. Wenn Sie einen bekommen, können Sie den Upstream, der ihn erzeugt, nicht reparieren. Sie könnte es beheben surrogatepass Fehler-Handler:

>>> "\ud83d\ude4f".encode('utf-16', 'surrogatepass').decode('utf-16') 
'' 

Python 2 was more permissive.

Hinweis: Auch wenn Ihre JSON-Datei Literal enthält \ ud83d \ ude4f (Zeichen); Sie sollen nicht das Ersatzpaar erhalten:

>>> print(ascii(json.loads(r'"\ud83d\ude4f"'))) 
'\U0001f64f' 

Hinweis: das Ergebnis ist Charakter ('\U0001f64f'), nicht das Ersatzpaar ('\ud83d\ude4f').

+0

Ehrfürchtig, danke! Ich habe den Fehlerhandler 'surrogatepass' übersehen. – MattDMo