2016-07-01 14 views
14

Questo è un seguito a Converting to Emoji. In questa domanda, l'OP aveva un file con codifica json.dumps() con un'emoji rappresentata come una coppia surrogata - \ud83d\ude4f. Aveva problemi a leggere il file e a tradurre correttamente l'emoji, e il corretto answer era a json.loads() ogni riga del file e il modulo json gestiva la conversione da una coppia di surrogati a (sto assumendo la codifica UTF8) emoji.Come lavorare con coppie surrogate in Python?

Così qui è la mia situazione: dire che ho solo una stringa regolare Python 3 unicode con una coppia di surrogati in esso:

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

Come faccio ad elaborare questa stringa per ottenere una rappresentazione della emoji fuori di esso ? Sto cercando di ottenere qualcosa di simile:

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

ho provato:

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

In generale si ottiene un errore simile a UnicodeEncodeError: XXX codec can't encode character '\ud83d' in position 8: surrogates no allowed.

Sto eseguendo Python 3.5.1 su Linux, con $LANG impostato su en_US.UTF-8. Ho eseguito questi esempi sia nell'interprete Python sulla riga di comando, sia in IPython in esecuzione in Sublime Text - non sembrano esserci differenze.

risposta

21

Hai mescolato una stringa letterale \ud83d in un file JSON su disco (sei personaggi: \ u d 8 3 d) e un carattere singolau'\ud83d' (specificata utilizzando una stringa letterale di codice sorgente Python) in memoria. E 'la differenza tra len(r'\ud83d') == 6 e len('\ud83d') == 1 su Python 3.

Se vedete '\ud83d\ude4f' stringa Python (caratteri), allora c'è un bug a monte. Normalmente, non si dovrebbe ottenere una tale stringa. Se ne ottieni uno e non è possibile correggere upstream che lo genera; si potrebbe risolvere il problema utilizzando gestore surrogatepass errore:

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

Python 2 was more permissive.

Nota: anche se il file JSON contiene caratteri letterali \ ud83d \ ude4f(); Non si dovrebbe ottenere la coppia di surrogati:

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

Avviso: il risultato è carattere ('\U0001f64f'), non la coppia di surrogati ('\ud83d\ude4f').

+0

Fantastico, grazie! Mi mancava il gestore degli errori 'surrogatepass'. – MattDMo