web-dev-qa-db-ja.com

Python - 'ascii'コーデックはバイトをデコードできません

私は本当に混乱しています。エンコードしようとしましたが、エラーは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は内部で何をしているのでしょうか。

111
thoslin
"你好".encode('utf-8')

encodeは、Unicodeオブジェクトをstringオブジェクトに変換します。しかし、ここではstringオブジェクトでそれを呼び出しました(あなたはuを持っていないので)。そのため、pythonは最初にstringunicodeオブジェクトに変換する必要があります。それでそれは同等のことをします

"你好".decode().encode('utf-8')

しかし、文字列がASCIIとして有効ではないため、デコードは失敗します。だからデコードできないという苦情があります。

157
Winston Ewert

常に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の "モグラを打つ"ことを避けたいのなら、データレベルで何が起こっているのかを理解することが重要です。ここでそれは別の方法で説明されています:

  • Unicodeオブジェクトはすでにデコードされています。decodeを呼び出す必要はありません。
  • Bytestringオブジェクトはすでにエンコードされています。encodeを呼び出すことは絶対に避けてください。

さて、バイト文字列の.encodeを見ると、Python 2はまず暗黙的にそれをテキスト(unicodeオブジェクト)に変換しようとします。同様に、ユニコード文字列の.decodeを見ると、Python 2は暗黙的にそれをバイト(strオブジェクト)に変換しようとします。

これらの暗黙の変換が、Unicodeを呼び出したときにDecodeErrorencodeを取得できる理由です。それは、エンコーディングが通常unicode型のパラメータを受け取るからです。 strパラメータを受け取ると、別のエンコーディングで再エンコードする前に、unicode型のオブジェクトに暗黙的にデコードされます。この変換はデフォルトの 'ASCII'デコーダを選択しますエンコーダ内でデコードエラーが発生します。

実際、Python 3ではメソッドstr.decodebytes.encodeは存在しません。彼らの除去は、この一般的な混乱を避けるための[物議を醸す]試みでした。

...あるいはsys.getdefaultencoding()が言及しているコーディング。通常これは 'ASCII'です。

51
wim

あなたはこれを試すことができます

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

または

あなたもフォローしようとすることができます

.pyファイルの先頭に次の行を追加します。

# -*- coding: utf-8 -*- 
39
Dadaso Zanzane

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

8
Johnsyweb

Unicode文字列をエンコードするにはu"你好".encode('utf8')を使います。しかし"你好"を表現したい場合は、それをデコードする必要があります。と同じように:

"你好".decode("utf8")

あなたはあなたが望むものを手に入れるでしょう。多分あなたはエンコード&デコードについてもっと学ぶべきです。

3
Qingtian

あなたがUnicodeを扱っているのであれば、時にはencode('utf-8')の代わりに、あなたはまた特殊文字を無視することを試みることができます。

"你好".encode('ascii','ignore')

またはas ここで提案されているようにsomething.decode('unicode_escape').encode('ascii','ignore')

この例では特に有用ではありませんが、特殊文字を変換できない場合は他のシナリオでうまく機能する可能性があります。

あるいは、 replace()を使って特定の文字を置き換える と考えることもできます。

3
kenorb

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(またはシステム内のロケール定義を管理するファイル)を編集することもできます。

0
0range