2016-07-01 23 views
14

Jest to kontynuacja do Converting to Emoji. W tym pytaniu OP miał plik z kodowaniem json.dumps() z emoji reprezentowanym jako para zastępcza - \ud83d\ude4f. Miał problemy z odczytaniem pliku i prawidłowym tłumaczeniem emoji, a poprawna answer była json.loads() każda linia z pliku, a moduł json obsłużyłby konwersję z pary zastępczej z powrotem do (zakładam kodowanie UTF8) emoji.Jak pracować z zastępczymi parami w Pythonie?

Więc tutaj jest moja sytuacja: że mam tylko regularne Python 3 Unicode ciąg z zastępczym pary w nim:

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

jaki sposób przetwarzać ten ciąg, aby uzyskać reprezentację emoji z niego ? Czekam na coś takiego:

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

Próbowałem:

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

Ogólnie otrzymuję komunikat o błędzie podobny do UnicodeEncodeError: XXX codec can't encode character '\ud83d' in position 8: surrogates no allowed.

Używam Python 3.5.1 w systemie Linux, z $LANG ustawionym na en_US.UTF-8. Uruchomiłem te próbki zarówno w interpreterze Pythona w linii poleceń, jak iw IPythonie działającym w Sublime Text - nie wydaje się, żeby były jakieś różnice.

Odpowiedz

21

pan mieszać ciągiem znaków \ud83d w pliku json na dysku (sześć znaków: \ u d 8 3 d) i pojedynczy charakter u'\ud83d' (określone przy użyciu ciąg dosłowne w kodzie źródłowym Pythona) w pamięci. Jest to różnica między len(r'\ud83d') == 6 i len('\ud83d') == 1 na Python 3.

Jeśli widzisz '\ud83d\ude4f' Python ciąg (znaków), to nie jest błąd w górę. Normalnie nie powinieneś dostawać takiego ciągu. Jeśli ją otrzymasz i nie możesz naprawić źródła, które je generuje; można to naprawić za pomocą obsługi surrogatepass błędzie:

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

Python 2 was more permissive.

Uwaga: nawet jeśli twój plik json zawiera literalne znaki \ ud83d \ ude4f(); nie należy się zastępczym parę:

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

Uwaga: wynik jest charakter ('\U0001f64f'), a nie parę zastępczym ('\ud83d\ude4f').

+0

Niesamowite, dzięki! Brakowało mi obsługi błędu "surrogatepass". – MattDMo