126

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

4

7 に答える 7

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

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

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

ただし、文字列が有効なASCIIではないため、デコードは失敗します。そのため、デコードできないという苦情が寄せられます。

于 2012-03-10T05:34:51.730 に答える
53

常にUnicodeからバイトにエンコードします。
この方向では、エンコーディングを選択できます

>>> u"你好".encode("utf8")
'\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print _
你好

もう1つの方法は、バイトからユニコードにデコードすることです。
この方向では、エンコーディングが何であるかを知る必要があります

>>> bytes = '\xe4\xbd\xa0\xe5\xa5\xbd'
>>> print bytes
你好
>>> bytes.decode('utf-8')
u'\u4f60\u597d'
>>> print _
你好

この点は十分に強調することはできません。Unicodeの「モグラたたき」を避けたい場合は、データレベルで何が起こっているのかを理解することが重要です。ここでは別の方法で説明します。

  • Unicodeオブジェクトはすでにデコードされているので、呼び出す必要はありませんdecode
  • バイトストリングオブジェクトはすでにエンコードされているので、呼び出す必要はありませんencode

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

これらの暗黙の変換は、を呼び出したときに取得できる理由です。これは、エンコーディングが通常、タイプのパラメータを受け入れるためです。パラメータを受け取ると、別のエンコーディングで再エンコードする前に、あるタイプのオブジェクトに暗黙的にデコードされます。この変換では、デフォルトの「ASCII」デコーダー†</ sup>が選択され、エンコーダー内のデコードエラーが発生します。UnicodeDecodeErrorencodeunicodestrunicode

実際、Python 3にはメソッドがstr.decodeありbytes.encode、存在すらしていません。それらの除去は、この一般的な混乱を回避するための[物議を醸す]試みでした。

†</sup> ...またはコーディングsys.getdefaultencoding()で言及されているもの。通常、これは「ASCII」です。

于 2012-03-10T05:14:14.017 に答える
41

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

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

または

フォローすることもできます

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

# -*- coding: utf-8 -*- 
于 2016-01-04T13:00:19.077 に答える
8

Python <3を使用している場合は、文字列リテラルの前に:を付けて、文字列リテラルがUnicodeであることをuインタプリタに通知する必要があります。

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'

さらに読むUnicodeHOWTO

于 2012-03-10T05:14:15.500 に答える
3

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

"你好".decode("utf8")

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

于 2013-12-19T03:37:37.283 に答える
3

Unicodeを扱っている場合は、の代わりにencode('utf-8')、特殊文字を無視することもできます。

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

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

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

または、を使用して特定の文字を置き換えるreplace()ことを検討できます。

于 2017-05-28T16:36:09.367 に答える
2

Linuxまたは同様のシステム(BSD、Macについては不明)のシェルからPythonインタープリターを起動する場合は、シェルのデフォルトのエンコードも確認する必要があります。

locale charmap(Pythonインタープリターではなく)シェルから呼び出すと、次のように表示されます。

[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

これが当てはまらず、他の何かが表示された場合、たとえば

[user@host dir] $ locale charmap
ANSI_X3.4-1968
[user@host dir] $ 

Pythonは(少なくとも私の場合などの場合)シェルのエンコーディングを継承し、(一部?すべて?)ユニコード文字を印刷できなくなります。sys.getdefaultencoding()を介して表示および制御するPython独自のデフォルトのエンコーディングでsys.setdefaultencoding()あり、この場合は無視されます。

この問題が発生した場合は、次の方法で修正できます。

[user@host dir] $ export LC_CTYPE="en_EN.UTF-8"
[user@host dir] $ locale charmap
UTF-8
[user@host dir] $ 

(または、en_ENの代わりに必要なキーマップを選択します。)/etc/locale.confこれを修正するために編集(またはシステムのロケール定義を管理するファイル)することもできます。

于 2018-09-27T22:51:27.667 に答える