私は本当に混乱しています。エンコードしようとしましたが、エラーはcan't decode...
です。
>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
私は、文字列の前に "u"を付けてエラーを回避する方法を知っています。 encodeが呼び出されたときにエラーが「デコードできない」のはなぜなのかと疑問に思います。 Pythonは内部で何をしているのでしょうか。
"你好".encode('utf-8')
encode
は、Unicodeオブジェクトをstring
オブジェクトに変換します。しかし、ここではstring
オブジェクトでそれを呼び出しました(あなたはuを持っていないので)。そのため、pythonは最初にstring
をunicode
オブジェクトに変換する必要があります。それでそれは同等のことをします
"你好".decode().encode('utf-8')
しかし、文字列がASCIIとして有効ではないため、デコードは失敗します。だからデコードできないという苦情があります。
常にUnicodeからバイトにエンコードします。
この方向では、あなたはエンコーディングを選ぶようになる。
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print _
你好
他の方法はバイトからユニコードにデコードすることです。
この方向では、エンコーディングが何であるかを知っておく必要があります。
>>> bytes = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print bytes
你好
>>> bytes.decode('utf-8')
u'\u4f60\u597d'
>>> print _
你好
この点は十分強調することはできません。あなたがUnicodeの "モグラを打つ"ことを避けたいのなら、データレベルで何が起こっているのかを理解することが重要です。ここでそれは別の方法で説明されています:
decode
を呼び出す必要はありません。encode
を呼び出すことは絶対に避けてください。さて、バイト文字列の.encode
を見ると、Python 2はまず暗黙的にそれをテキスト(unicode
オブジェクト)に変換しようとします。同様に、ユニコード文字列の.decode
を見ると、Python 2は暗黙的にそれをバイト(str
オブジェクト)に変換しようとします。
これらの暗黙の変換が、Unicode
を呼び出したときにDecode
Error
encode
を取得できる理由です。それは、エンコーディングが通常unicode
型のパラメータを受け取るからです。 str
パラメータを受け取ると、別のエンコーディングで再エンコードする前に、unicode
型のオブジェクトに暗黙的にデコードされます。この変換はデフォルトの 'ASCII'デコーダを選択します†エンコーダ内でデコードエラーが発生します。
実際、Python 3ではメソッドstr.decode
とbytes.encode
は存在しません。彼らの除去は、この一般的な混乱を避けるための[物議を醸す]試みでした。
†...あるいはsys.getdefaultencoding()
が言及しているコーディング。通常これは 'ASCII'です。
あなたはこれを試すことができます
import sys
reload(sys)
sys.setdefaultencoding("utf-8")
または
あなたもフォローしようとすることができます
.pyファイルの先頭に次の行を追加します。
# -*- coding: utf-8 -*-
Python <3を使用している場合は、 文字列リテラルの先頭にu
を付けてUnicodeであることをインタプリタに通知する必要があります。
Python 2.7.2 (default, Jan 14 2012, 23:14:09)
[GCC 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> "你好".encode("utf8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe4 in position 0: ordinal not in range(128)
>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
さらに読む: Unicode HOWTO 。
Unicode文字列をエンコードするにはu"你好".encode('utf8')
を使います。しかし"你好"
を表現したい場合は、それをデコードする必要があります。と同じように:
"你好".decode("utf8")
あなたはあなたが望むものを手に入れるでしょう。多分あなたはエンコード&デコードについてもっと学ぶべきです。
あなたがUnicodeを扱っているのであれば、時にはencode('utf-8')
の代わりに、あなたはまた特殊文字を無視することを試みることができます。
"你好".encode('ascii','ignore')
またはas ここで提案されているようにsomething.decode('unicode_escape').encode('ascii','ignore')
。
この例では特に有用ではありませんが、特殊文字を変換できない場合は他のシナリオでうまく機能する可能性があります。
あるいは、 replace()
を使って特定の文字を置き換える と考えることもできます。
Linuxまたは類似のシステム(BSD、Macについてはわからない)でシェルからPythonインタプリタを起動する場合は、シェルのデフォルトのエンコーディングも確認する必要があります。
シェル(pythonインタプリタではありません)からlocale charmap
を呼び出すと表示されるはずです
[user@Host dir] $ locale charmap
UTF-8
[user@Host dir] $
そうでない場合は、他に何かが表示されます。
[user@Host dir] $ locale charmap
ANSI_X3.4-1968
[user@Host dir] $
Pythonは(少なくとも私のようないくつかのケースでは)シェルのエンコーディングを継承し、(いくつかの、すべての)Unicode文字を印刷することはできません。 sys.getdefaultencoding()
およびsys.setdefaultencoding()
を介して表示および制御するPython独自のデフォルトエンコーディングは、この場合無視されます。
あなたがこの問題を抱えているとわかった場合、あなたはそれを修正することができます。
[user@Host dir] $ export LC_CTYPE="en_EN.UTF-8"
[user@Host dir] $ locale charmap
UTF-8
[user@Host dir] $
これを修正するために/etc/locale.conf
(またはシステム内のロケール定義を管理するファイル)を編集することもできます。