UnicodeEncodeError, der größte natürliche Feind (Übertreibung) für Python-Programmierer (mit Python2), die mit Japanisch umgehen. Die Person neben mir war gestern die Beute, und während ich bei der Lösung half, konnte ich die Richtung der Zeichenfolgenverarbeitung in Python 2 ein wenig bestimmen. (Ich möchte bald eine Python 3-Version zusammenstellen)
Die Byte-Zeichenfolge wird durch eine bestimmte Codierungsmethode (z. B. Utf-8) codiert und im Literal als "das" ausgedrückt. Andererseits ist eine Unicode-Zeichenfolge eine Anordnung von Unicode-Codepunkten, und im Literal wird "u" wie "u" hinzugefügt.
python
(py2.7)~ » ipython
(Kürzung)
>>> 'Ah' #Byte-String
Out[1]: '\xe3\x81\x82'
>>> u'Ah' #Unicode-Zeichenfolge
Out[2]: u'\u3042'
>>> 'Ah'.decode('utf-8') (or unicode('Ah', 'utf-8')) #Byte-String->Unicode-Zeichenfolge(=Dekodieren)
Out[3]: u'\u3042'
>>> u'Ah'.encode('utf-8') #Unicode-Zeichenfolge->Byte-String(=Kodieren)
Out[4]: '\xe3\x81\x82'
Wenn Sie mit der Funktion "Typ" prüfen, können Sie feststellen, dass die Byte-Zeichenfolge vom Typ "Str" / die Unicode-Zeichenfolge vom Typ "Unicode" ist.
python
>>> type('a')
Out[5]: str
>>> type(u'a')
Out[6]: unicode
Darüber hinaus sind in Python2 sowohl Byte-Strings als auch Unicode-Strings Strings und können verkettet werden.
python
>>> u'a' + 'a'
Out[7]: u'aa'
Ja, ich muss mich mit Japanisch auseinandersetzen (um genau zu sein, alle Nicht-ASCII-Zeichen)! Wie Sie der Ausgabe des obigen Beispiels entnehmen können, wird durch Kombinieren einer Unicode-Zeichenfolge und einer Byte-Zeichenfolge eine Unicode-Zeichenfolge erstellt. Dabei müssen Sie die Byte-Zeichenfolge in eine Unicode-Zeichenfolge dekodieren. Das Problem hierbei ist jedoch, dass die Python-Zeichenfolge keine Informationen zu ihrer eigenen Codierung enthält.
"Wenn Sie nicht wissen, wie man codiert, können Sie es in ASCII decodieren", sagt Python und Hello UnicodeEncodeError. Es ist selten, dass Literale solche Fehler machen, aber es ist leicht, Fehler zu machen, wenn Sie nicht auf die Zeichenfolgen achten, die von außerhalb Ihres eigenen Programms empfangen werden (einschließlich Standardeingabe / -ausgabe).
python
>>> u'a' + 'Ah' #Unicode-Zeichenfolge und Byte-Zeichenfolge(Nicht-ASCII)Kombinieren
---------------------------------------------------------------------------
UnicodeDecodeError Traceback (most recent call last)
<ipython-input-8-084e015bd795> in <module>()
----> 1 u'a' + 'Ah'
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)
>>> u'a' + 'Ah'.decode('utf-8') #Byte-String->Unicode-Zeichenfolge
Out[9]: u'a\u3042'
>>> print(u'a' + 'Ah'.decode('utf-8'))
a ah
Der Grund für die Umstellung auf eine Unicode-Zeichenfolge anstelle einer Byte-Zeichenfolge besteht darin, dass es häufig bequemer ist, mit einer Zeichenfolge auf Codepunktebene als auf Byte-Ebene zu arbeiten. Wenn Sie beispielsweise die Anzahl der Zeichen zählen möchten, können Sie die Funktion len
für Unicode-Zeichenfolgen verwenden. Andererseits gibt eine Byte-Zeichenfolge die Anzahl der Bytes zurück, sodass sie nicht mit dieser Absicht verwendet werden kann.
python
>>> len(u'Ah')
Out[11]: 3
>>> len('Ah')
Out[12]: 9
Ist nicht. Betrachten Sie als Beispiel das folgende einfache Programm.
test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
print(u'Ah' + u'Sagen')
Versuchen Sie es im Terminal. Wahrscheinlich kann die Mehrheit der Menschen dies ohne Probleme tun.
python
(py2.7)~ » python test.py
Ah
Wie wäre es also damit, die Ausführungsergebnisse in eine Datei umzuleiten? Es gibt viele Umgebungen, in denen UnicodeEncodeError wie unten gezeigt auftritt.
python
(py2.7)~ » python test.py > test.txt
Traceback (most recent call last):
File "test.py", line 4, in <module>
print(u'Ah')
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128)
Im Beispiel print (u'Ai ')
wird eine Unicode-Zeichenfolge an die Standardausgabe übergeben, aber zu diesem Zeitpunkt wird die Unicode-Zeichenfolge-> Byte-Zeichenfolge konvertiert (codiert).
Wenn die Standardeingabe / -ausgabe mit dem Terminal verbunden ist, wählt Python automatisch die entsprechende Codierungsmethode aus dem Wert des Gebietsschemas aus (z. B. Umgebungsvariable LANG). Wenn andererseits die Standardeingabe / -ausgabe durch Umleitung usw. mit einem anderen als dem Terminal verbunden ist, können keine Informationen zum Auswählen einer geeigneten Codierungsmethode erhalten werden, und die Codierung wird in ASCII und in den meisten Fällen versucht (= wenn Nicht-ASCII-Zeichen enthalten sind). Scheitern.
(ref.) http://blog.livedoor.jp/dankogai/archives/51816624.html
Das Codieren der Unicode-Zeichenfolge vor dem Übergeben an die Standardausgabe kann dieses Problem lösen.
test.py(Unicode-Zeichenfolge->Byte-String)
#!/usr/bin/env python
# -*- coding: utf-8 -*-
print((u'Ah' + u'Sagen').encode('utf-8'))
Durch Angabe der Umgebungsvariablen "PYTHONIOENCODING" kann die verwendete Codierungsmethode unabhängig vom Gebietsschema festgelegt werden. Wenn Sie dies angeben, müssen Sie es nicht einzeln codieren.
python
(py2.7)~ » cat test.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
print(u'Ah' + u'Sagen')
(py2.7)~ » PYTHONIOENCODING=utf-8 python test.py > test.txt
(py2.7)~ » cat test.txt
Ah
(ref.) http://methane.hatenablog.jp/entry/20120806/1344269400
Recommended Posts