2013-07-08 5 views
5

Ich habe versucht, ein einfaches Skript zu schreiben, das Benutzereingaben (von einem iPhone) in eine Textdatei speichern kann. Das Problem, das ich habe ist, dass, wenn ein Benutzer ein Emoji-Symbol verwendet, es die ganze Sache bricht.Python schreiben (iPhone) Emoji in eine Datei

OS: Ubuntu

Python Version: 2.7.3

derzeit Mein Code wie dieses

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

sieht Wenn ein Emoji-Zeichen in der Beschreibung Variable übergeben wird, erhalte ich die Fehlermeldung:

UnicodeEncodeError: Codecode 'ascii' kann Zeichen in Position 7-8 nicht codieren: Ordnungszahl nicht im Bereich (128)

Jede mögliche Hilfe wird geschätzt.

+0

Ist 'json_obj [" description "]' ein 'Unicode' oder ein' str'? Wenn letzteres, in welcher Kodierung ist es? Können Sie auch 'repr (json_obj [" description "]) direkt vor dem Fehler ausdrucken, damit wir sehen können, was Sie tatsächlich drucken möchten? – abarnert

+0

Woher kommt 'json_obj' auch? Der Name impliziert das stdlib 'json'-Modul, aber die Tatsache, dass die Schlüssel und Werte anscheinend" str "sind, bedeutet, dass es nicht ... – abarnert

Antwort

3

Das wahrscheinlichste Problem hier ist, dass json_obj["description"] ist eigentlich ein UTF-8-codierte str, kein unicode. Also, wenn Sie versuchen, write es zu einer codecs-Wrapped-Datei, muss Python es von str zu unicode zu entschlüsseln, so dass es neu codieren kann. Und das ist der Teil, der fehlschlägt, weil diese automatische Decodierung sys.getdefaultencoding() verwendet, was 'ascii' ist.

Zum Beispiel:

>>> 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) 

Es gibt zwei mögliche Lösungen hier.

Zuerst können Sie alles so schnell wie möglich explizit zu unicode dekodieren. Ich bin mir nicht sicher, woher Ihre json_obj stammt, aber ich vermute, dass es nicht die stdlib json.loads ist, weil das standardmäßig unicode Schlüssel und Werte gibt. Wenn Sie JSON mit den stdlib-Funktionen ersetzen, wird das Problem wahrscheinlich gelöst.

Zweitens können Sie alles als UTF-8 str Objekte verlassen und im Binärmodus bleiben. Wenn Sie wissen, dass Sie UTF-8 überall haben, nur open die Datei anstelle von codecs.open, und schreiben Sie ohne jegliche Codierung.


Außerdem sollten Sie stark statt codecs.open mit io.open betrachten. Es hat eine Reihe von Vorteilen, einschließlich:

  • Löst eine Ausnahme statt die falsche Sache zu tun, wenn Sie es falsche Werte übergeben.
  • Oft schneller.
  • Forward-kompatibel mit Python 3.
  • Hat eine Reihe von Bugfixes, die nie zurück portiert werden codecs.

Der einzige Nachteil ist, dass es nicht abwärtskompatibel zu Python 2.5 ist. Wenn Ihnen das nicht wichtig ist, verwenden Sie nicht codecs.