2013-07-08 4 views
5

Ho cercato di scrivere un semplice script in grado di salvare l'input dell'utente (proveniente da un iPhone) in un file di testo. Il problema che sto avendo è che quando un utente usa un'icona Emoji, rompe il tutto.Scrittura di Python (iPhone) Emoji in un file

OS: Ubuntu

Python Versione: 2.7.3

Il mio codice attualmente appare così

f = codecs.open(path, "w+", encoding="utf8") 
f.write("Desc: " + json_obj["description"]) 
f.close() 

Quando un carattere Emoji viene passato nella variabile descrizione, ottengo l'errore:

UnicodeEncodeError: il codec 'ascii' non può codificare i caratteri nella posizione 7-8: ordinale non compreso nell'intervallo (128)

Qualsiasi aiuto possibile è apprezzato.

+0

È 'json_obj [" description "]' a 'unicode' o a' str'? Se quest'ultimo, in che codifica è? Inoltre, puoi 'stampare repr (json_obj [" description "])' subito prima dell'errore, in modo che possiamo vedere cosa stai effettivamente cercando di stampare? – abarnert

+0

Inoltre, da dove proviene 'json_obj'? Il nome implica il modulo stdlib 'json', ma il fatto che le chiavi e i valori siano apparentemente' str' implica che non sia ... – abarnert

risposta

3

Il problema più probabile è che json_obj["description"] è in realtà un codice str codificato in UTF-8, non uno . Quindi, quando si prova a in un file wrapper codecs, Python deve decodificarlo da str a unicode in modo che possa ricodificarlo. E quella è la parte che non riesce, perché quella decodifica automatica utilizza sys.getdefaultencoding(), che è 'ascii'.

Ad esempio:

>>> f = codecs.open('emoji.txt', 'w+', encoding='utf-8') 
>>> e = u'\U0001f1ef' 
>>> print e 

>>> e 
u'\U0001f1ef' 
>>> f.write(e) 
>>> e8 = e.encode('utf-8') 
>>> e8 
'\xf0\x9f\x87\xaf' 
>>> f.write(e8) 
UnicodeDecodeError: 'ascii' codec can't decode byte 0xf0 in position 0: ordinal not in range(128) 

Ci sono due possibili soluzioni qui.

Innanzitutto, è possibile decodificare in modo esplicito tutto a unicode il prima possibile. Non sono sicuro da dove provenga il tuo json_obj, ma sospetto che non sia in realtà lo stdlib json.loads, perché per impostazione predefinita, questo ti da sempre chiavi e valori unicode. Quindi, la sostituzione di qualsiasi cosa tu stia utilizzando per JSON con le funzioni stdlib probabilmente risolverà il problema.

In secondo luogo, è possibile lasciare tutto come UTF-8 str oggetti e rimanere in modalità binaria. Se sai di avere UTF-8 ovunque, solo il open il file invece di codecs.open e scrivi senza alcuna codifica.


Inoltre, si dovrebbe prendere in seria considerazione utilizzando io.open invece di codecs.open. Ha una serie di vantaggi, tra cui:

  • Solleva un'eccezione invece di fare la cosa sbagliata se si passa valori errati.
  • Spesso più veloce.
  • Inoltrabile con Python 3.
  • Ha una serie di correzioni di bug che non verranno mai ritrasportate a codecs.

L'unico svantaggio è che non è retrocompatibile con Python 2.5. A meno che ciò sia importante per te, non utilizzare codecs.