web-dev-qa-db-ja.com

修正方法: "UnicodeDecodeError: 'ascii'コーデックはバイトをデコードできません"

as3:~/ngokevin-site# nano content/blog/20140114_test-chinese.mkd
as3:~/ngokevin-site# wok
Traceback (most recent call last):
File "/usr/local/bin/wok", line 4, in
Engine()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 104, in init
self.load_pages()
File "/usr/local/lib/python2.7/site-packages/wok/engine.py", line 238, in load_pages
p = Page.from_file(os.path.join(root, f), self.options, self, renderer)
File "/usr/local/lib/python2.7/site-packages/wok/page.py", line 111, in from_file
page.meta['content'] = page.renderer.render(page.original)
File "/usr/local/lib/python2.7/site-packages/wok/renderers.py", line 46, in render
return markdown(plain, Markdown.plugins)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 419, in markdown
return md.convert(text)
File "/usr/local/lib/python2.7/site-packages/markdown/init.py", line 281, in convert
source = unicode(source)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128). -- Note: Markdown only accepts unicode input!

それを修正するには?

他のPythonベースの静的ブログアプリの中には、中国語の投稿を正常に公開できるものがあります。このアプリのように: http://github.com/vrypan/bucket3 。私のサイト http://bc3.brite.biz/ では、中国の投稿はうまく公開できます。

350
fisherman

ついにできた:

as3:/usr/local/lib/python2.7/site-packages# cat sitecustomize.py
# encoding=utf8  
import sys  

reload(sys)  
sys.setdefaultencoding('utf8')

確認させてください:

as3:~/ngokevin-site# python
Python 2.7.6 (default, Dec  6 2013, 14:49:02)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> reload(sys)
<module 'sys' (built-in)>
>>> sys.getdefaultencoding()
'utf8'
>>>

上記のpythonのデフォルトエンコーディングはutf8です。それからエラーはもうありません。

473
fisherman

一般的な答えを使用しないでください(sys.setdefaultencoding('utf8')

問題を隠し、Python 3.xへの移行を妨げるのは厄介なハックです(reloadを使用する必要がある理由があります)。問題を理解し、根本原因を修正し、そしてUnicodeの禅を楽しんでください。 を参照してください。 詳細はこちら

tl; dr/quick fix

  • 何もしないでデコード/エンコードしない
  • あなたの文字列がUTF-8でエンコードされていると仮定しないでください
  • コード内でできるだけ早く文字列をUnicode文字列に変換するようにしてください。

Python 2.xのUnicode Zen - ロングバージョン

原因が分からなければ根本的な原因を知るのは難しいので、一般的に話さなければなりません。

UnicodeDecodeError: 'ascii' codec can't decode byteは一般に、元の文字列のエンコーディングを指定せずに、非ASCII文字を含むPython 2.x strをUnicode文字列に変換しようとしたときに発生します。

簡単に言うと、Unicode文字列は、まったく別の種類のPython文字列で、エンコーディングは含まれていません。これらはUnicode ポイントコードのみを保持しているため、スペクトル全体からの任意のUnicodeポイントを保持できます。文字列はUTF-8、UTF-16、ISO-8895-1、GBK、Big5などのエンコードされたテキストを含みます。ストリングはUnicodeに​​デコードされ、Unicodeはストリングにエンコードされます。ファイルとテキストデータは常にエンコードされた文字列で転送されます。

Markdownモジュールの作者は、おそらくunicode()(例外がスローされる場所)を残りのコードへの良質の門として使うでしょう - それはASCIIを変換するか、または既存のUnicode文字列を新しいUnicode文字列に再ラップします。 Markdownの作者は入力文字列のエンコーディングを知ることができないので、Markdownに渡す前に文字列をUnicode文字列にデコードするのはあなたに頼ります。

Unicode文字列は、文字列の接頭辞uを使用してコード内で宣言できます。例えば。

>>> my_u = u'my ünicôdé strįng'
>>> type(my_u)
<type 'unicode'>

Unicode文字列はファイル、データベース、ネットワークモジュールからも来ます。こうなっても、エンコーディングについて心配する必要はありません。

ガッチャ

明示的にunicode()を呼び出さない場合でも、strからUnicodeへの変換が発生する可能性があります。

以下のシナリオでは、UnicodeDecodeError例外が発生します。

# Explicit conversion without encoding
unicode('€')

# New style format string into Unicode string
# Python will try to convert value string to Unicode first
u"The currency is: {}".format('€')

# Old style format string into Unicode string
# Python will try to convert value string to Unicode first
u'The currency is: %s' % '€'

# Append string to Unicode
# Python will try to convert string to Unicode first
u'The currency is: ' + '€'         

次の図では、端末の種類に応じてWord caféが "UTF-8"または "Cp1252"エンコーディングでエンコードされていることがわかります。両方の例で、cafは通常のASCIIです。 UTF-8では、éは2バイトを使用してエンコードされます。 "Cp1252"では、éは0xE9です(これはUnicodeのポイント値でもあります(偶然の一致ではありません))。正しいdecode()が呼び出され、Python Unicodeへの変換は成功しました: Diagram of a string being converted to a Python Unicode string

この図では、decode()asciiで呼び出されています(これは、エンコーディングを指定せずにunicode()を呼び出すのと同じです)。 ASCIIは0x7Fより大きなバイトを含むことができないので、これはUnicodeDecodeError例外を投げます:

Diagram of a string being converted to a Python Unicode string with the wrong encoding

Unicodeサンドイッチ

コードにUnicodeサンドイッチを作成して、すべての受信データをUnicode文字列にデコードし、Unicodeを使用してから、途中でstrsにエンコードすることをお勧めします。これにより、コードの途中での文字列のエンコードについて心配する必要がなくなります。

入力/デコード

ソースコード

あなたのソースコードに非ASCII文字を焼き付ける必要がある場合は、文字列の先頭にuを付けてUnicode文字列を作成してください。例えば。

u'Zürich'

Pythonでソースコードをデコードできるようにするには、ファイルの実際のエンコードと一致するようにエンコードヘッダーを追加する必要があります。たとえば、ファイルが「UTF-8」としてエンコードされている場合は、次のようにします。

# encoding: utf-8

これはあなたのソースコードに非ASCIIコードがある場合にのみ必要です

ファイル

通常、非ASCIIデータはファイルから受信されます。 ioモジュールは、与えられたencodingを使ってファイルをオンザフライでデコードするTextWrapperを提供します。ファイルには正しいエンコードを使用する必要があります - 簡単に推測することはできません。たとえば、UTF-8ファイルの場合:

import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
     my_unicode_string = my_file.read() 

my_unicode_stringはMarkdownに渡すのに適しています。 read()行のUnicodeDecodeErrorの場合は、おそらく間違ったエンコード値を使用したことになります。

CSVファイル

Python 2.7 CSVモジュールは非ASCII文字をサポートしていません????。ただし、 https://pypi.python.org/pypi/backports.csv を使用してヘルプを入手できます。

上記のように使用しますが、開いたファイルを渡します。

from backports import csv
import io
with io.open("my_utf8_file.txt", "r", encoding="utf-8") as my_file:
    for row in csv.reader(my_file):
        yield row

データベース

ほとんどのPythonデータベースドライバはUnicodeでデータを返すことができますが、通常は少し設定が必要です。 SQLクエリには常にUnicode文字列を使用してください。

接続文字列に以下を追加します。

charset='utf8',
use_unicode=True

例えば。

>>> db = MySQLdb.connect(Host="localhost", user='root', passwd='passwd', db='sandbox', use_unicode=True, charset="utf8")

追加:

psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
psycopg2.extensions.register_type(psycopg2.extensions.UNICODEARRAY)

HTTP

Webページは、ほぼあらゆるエンコード方式でエンコードできます。 Content-typeヘッダーには、エンコーディングを暗示するためのcharsetフィールドを含める必要があります。コンテンツはこの値に対して手動でデコードできます。あるいは、 Python-Requests はUnicodeをresponse.textに返します。

手動で

文字列を手動でデコードする必要がある場合は、単にmy_string.decode(encoding)を実行できます。ここでencodingは適切なエンコードです。 Python 2.xでサポートされているコーデックはここにあります: 標準エンコーディング 。繰り返しますが、UnicodeDecodeErrorを取得した場合は、おそらく間違ったエンコーディングを使用しているはずです。

サンドイッチの肉

通常のstrsと同じようにUnicodeを操作します。

出力

標準出力/印刷

printは、標準出力ストリームを介して書き込みます。 Pythonは、Unicodeがコンソールのエンコーディングにエンコードされるように、標準出力にエンコーダーを設定しようとします。たとえば、Linuxシェルのlocaleen_GB.UTF-8の場合、出力はUTF-8にエンコードされます。 Windowsでは、8ビットコードページに制限されます。

ロケールの破損など、コンソールの設定が正しくないと、予期しない印刷エラーが発生する可能性があります。 PYTHONIOENCODING環境変数は標準出力のエンコーディングを強制することができます。 

ファイル

入力と同様に、io.openを使用してUnicodeをエンコードされたバイト文字列に透過的に変換することができます。

データベース

読み取りと同じ設定で、Unicodeを直接書き込むことができます。

Python 3

Python 3では、Python 2.xと同等のUnicode対応はできませんが、通常のstrはUnicode文字列になり、古いstrbytesになります。 

デフォルトのエンコーディングはUTF-8になりました。エンコーディングを指定せずにバイト文字列を.decode()と指定した場合、Python 3はUTF-8エンコーディングを使用します。これはおそらく人々のUnicodeの問題の50%を修正しています。

さらに、open()はデフォルトでテキストモードで動作するので、デコードされたstr(Unicodeの1)を返します。エンコーディングはロケールに由来します。ロケールは、Un * xシステムではUTF-8、Windowsボックスではwindows-1251などの8ビットコードページです。

439

これが古典的な「Unicodeの問題」です。これを説明することは、何が起こっているのかを完全に説明するためのStackOverflow回答の範囲を超えていると思います。 

よく説明されている ここ

非常に簡単に要約すると、バイト文字列として解釈されるものをUnicode文字にデコードする必要があるものに渡しましたが、デフォルトのコーデック(ascii)が失敗しています。

あなたが指し示したプレゼンテーションはこれを避けるためのアドバイスを提供します。コードを「Unicodeサンドイッチ」にします。 Python 2では、 "from __future__ import unicode_literals"の使用が役に立ちます。

更新日:どのようにコードを修正することができます:

OK - あなたの変数の "source"には数バイトあります。彼らがどのようにしてそこに入ったかはあなたの質問からは明らかではありません - 多分あなたはそれらをウェブフォームから読んだ?いずれにせよ、それらはASCIIでエンコードされていませんが、pythonはそれらがUnicodeであると仮定してUnicodeに変換しようとしています。エンコーディングとは何かを明示的に伝える必要があります。これはあなたが 知る必要があることを意味します エンコーディングは何ですか!それは必ずしも容易ではありません、そしてそれは完全にこの文字列がどこから来たのかに依存します。 UTF-8など、いくつかの一般的なエンコーディングを試すことができます。 2番目のパラメータとしてエンコードをunicode()に伝えます。

source = unicode(source, 'utf-8')
119
GreenAsJade

場合によっては、デフォルトのエンコーディング(print sys.getdefaultencoding())を確認すると、ASCIIを使用していることが返されます。あなたがUTF-8に変更した場合、それはあなたの変数の内容によってはうまくいきません。 

import sys
reload(sys)  
sys.setdefaultencoding('Cp1252')
38
Davy
"UnicodeDecodeError: 'ascii' codec can't decode byte"

このエラーの原因:input_stringはUnicodeである必要がありますが、strが指定されています

"TypeError: Decoding Unicode is not supported"

このエラーの原因:Unicode input_stringをUnicodeに変換しようとしています


それで最初にあなたのinput_stringがstrであることを確認し、必要ならばUnicodeに変換してください:

if isinstance(input_string, str):
   input_string = unicode(input_string, 'utf-8')

次に、上記は型を変更するだけで、ASCII以外の文字は削除されません。 ASCII以外の文字を削除したい場合は、次のようにします。

if isinstance(input_string, str):
   input_string = input_string.decode('ascii', 'ignore').encode('ascii') #note: this removes the character and encodes back to string.

Elif isinstance(input_string, unicode):
   input_string = input_string.encode('ascii', 'ignore')
17

次のエラーメッセージを解決するために探していました。

unicodedecodeerror: 'ascii'コーデックが位置5454のバイト0xe2をデコードできない:序数が範囲外(128)

私はついに 'encoding'を指定することでそれを直しました:

f = open('../glove/glove.6B.100d.txt', encoding="utf-8")

それがあなたにも役立つことを願っています。

15
Zoe L

常にUnicodeに変換するのが最善だと思いますが、実際には、すべての引数をチェックして、何らかの形式の文字列処理を含むすべての関数やメソッドに変換する必要があるため、これを達成するのは困難です。

そこで、どちらの入力からもUnicodeまたはバイト文字列を保証するために、次のようなアプローチを思いつきました。手短に言うと、 以下のラムダを含めて 使用します。

# guarantee unicode string
_u = lambda t: t.decode('UTF-8', 'replace') if isinstance(t, str) else t
_uu = lambda *tt: Tuple(_u(t) for t in tt) 
# guarantee byte string in UTF8 encoding
_u8 = lambda t: t.encode('UTF-8', 'replace') if isinstance(t, unicode) else t
_uu8 = lambda *tt: Tuple(_u8(t) for t in tt)

例:

text='Some string with codes > 127, like Zürich'
utext=u'Some string with codes > 127, like Zürich'
print "==> with _u, _uu"
print _u(text), type(_u(text))
print _u(utext), type(_u(utext))
print _uu(text, utext), type(_uu(text, utext))
print "==> with u8, uu8"
print _u8(text), type(_u8(text))
print _u8(utext), type(_u8(utext))
print _uu8(text, utext), type(_uu8(text, utext))
# with % formatting, always use _u() and _uu()
print "Some unknown input %s" % _u(text)
print "Multiple inputs %s, %s" % _uu(text, text)
# but with string.format be sure to always work with unicode strings
print u"Also works with formats: {}".format(_u(text))
print u"Also works with formats: {},{}".format(*_uu(text, text))
# ... or use _u8 and _uu8, because string.format expects byte strings
print "Also works with formats: {}".format(_u8(text))
print "Also works with formats: {},{}".format(*_uu8(text, text))

これがもう少しあります これについての推論

8
miraculixx

Encodeは、Unicodeオブジェクトを文字列オブジェクトに変換します。文字列オブジェクトをエンコードしようとしていると思います。まず結果をUnicodeオブジェクトに変換してから、そのUnicodeオブジェクトを 'utf-8'にエンコードします。例えば

    result = yourFunction()
    result.decode().encode('utf-8')
5
RAFI AFRIDI

私は同じ問題を抱えていましたが、Python 3ではうまくいきませんでした。

enc = sys.getdefaultencoding()
file = open(menu, "r", encoding = enc)

ファイルを読み書きするときにはエンコーディングを設定する必要があります。

3
Reihan_amn

要するに、Python 2で正しいUnicode処理を保証するためには、

  • ファイルの読み書きにio.openを使う
  • from __future__ import unicode_literalsを使う
  • unicodeを使用するように他のデータ入力/出力(データベース、ネットワークなど)を設定する
  • 出力をutf-8に設定できない場合は、出力をそれらの出力に変換してくださいprint(text.encode('ascii', 'replace').decode())

説明については、@ Alastair McCormackの 詳細な回答 を参照してください。

2
idbrii

私は文字列 "PastelerãaMallorca"と同じ問題を抱えて、私はと解決した:

unicode("Pastelería Mallorca", 'latin-1')
2
Alle Pavesi

このエラーは、文字列にASCII以外の文字が含まれていて、適切なデコードを行わずにその文字列に対して操作を実行している場合に発生します。以下のように、列ID、テキスト、およびデコード文字を含むCSVファイルを読み込んでいます。

train_df = pd.read_csv("Example.csv")
train_data = train_df.values
for i in train_data:
    print("ID :" + i[0])
    text = i[1].decode("utf-8",errors="ignore").strip().lower()
    print("Text: " + text)
1
Sravya

Django(1.9.10)/ Python 2.7.5プロジェクトでは、頻繁にUnicodeDecodeError例外があります。主に、Unicode文字列をロギングに入力しようとしたときです。私は基本的に8ビットのアスキー文字列にフォーマットし、 '?'にない文字を置き換えるために任意のオブジェクトのためのヘルパー関数を作りました。私はそれが最善の解決策ではないと思いますが、デフォルトのエンコーディングはASCIIなので(そして私はそれを変更したくありません)それはそうするでしょう:

 def encode_for_logging(c、encoding = 'ascii'):
 isinstance(c、basestring):
 c.encode(encoding、 'replace')を返します。 ] Elif isinstance(c、Iterable):cのvに対する
 c_ = [] 
:
 c_.append(encode_for_logging(v、encoding))
 return c _ 
 else:
 encode_for_logging(unicode(c))を返します
`

1
Paul Bormans

非ASCII文字(値が128を超えるバイト)を含むURLで、同じエラーが発生しました

url = url.decode('utf8').encode('utf-8')

注:utf-8、utf8は単なるエイリアスです。 「utf8」または「utf-8」のみを使用しても同じように機能します

私の場合、Python 2.7で私のために働いたので、この割り当てがstr内部表現の「何か」を変更したと思います。つまり、 urlそして最後に文字列をtf-8strに入れ、すべての魔法を適切な場所に配置します。 PythonのUnicodeは私にとって黒魔術です。役に立つことを願って

1
Fabiano Tarlao

同じエラーが発生し、これは私のエラーを解決しました。ありがとうございます。ユニコード処理が異なるpython 2とpython 3は、ピクルスファイルをロードするのに非常に互換性がありません。そのため、python pickleのエンコーディング引数を使用してください。私のファイルがもともとpython 2.xバージョンで保存されていた間に私が私のpython 3.7からピクルス化されたデータを開こうとしていたとき私は私が同じような問題を解決するのを助けました。 https://blog.modest-destiny.com/posts/python-2-and-3-compatible-pickle-save-and-load/ 私は自分のスクリプトでload_pickle関数をコピーし、load_pickle(pickle_file)と呼びます。 )このように私のinput_dataをロードしながら:

input_data = load_pickle("my_dataset.pkl")

Load_pickle関数はここにあります:

def load_pickle(pickle_file):
    try:
        with open(pickle_file, 'rb') as f:
            pickle_data = pickle.load(f)
    except UnicodeDecodeError as e:
        with open(pickle_file, 'rb') as f:
            pickle_data = pickle.load(f, encoding='latin1')
    except Exception as e:
        print('Unable to load data ', pickle_file, ':', e)
        raise
    return pickle_data
0
Ganesh Shah

これは私のために働いた:

    file = open('docs/my_messy_doc.pdf', 'rb')
0
saran3h

これが私の解決策です。エンコーディングを追加するだけです。 with open(file, encoding='utf8') as f

そして、手袋ファイルを読むのは長い時間がかかるので、私は手袋ファイルをでたらめなファイルにすることを勧めます。あなたが埋め込み重みを読んだとき、それはあなたの時間を節約するでしょう。 

import numpy as np
from tqdm import tqdm


def load_glove(file):
    """Loads GloVe vectors in numpy array.
    Args:
        file (str): a path to a glove file.
    Return:
        dict: a dict of numpy arrays.
    """
    embeddings_index = {}
    with open(file, encoding='utf8') as f:
        for i, line in tqdm(enumerate(f)):
            values = line.split()
            Word = ''.join(values[:-300])
            coefs = np.asarray(values[-300:], dtype='float32')
            embeddings_index[Word] = coefs

    return embeddings_index

# EMBEDDING_PATH = '../embedding_weights/glove.840B.300d.txt'
EMBEDDING_PATH = 'glove.840B.300d.txt'
embeddings = load_glove(EMBEDDING_PATH)

np.save('glove_embeddings.npy', embeddings) 

要旨リンク: https://Gist.github.com/BrambleXu/634a844cdd3cd04bb2e3ba3c83aef227

0
Bramble

#encoding = utf-8 をPythonファイルの先頭に指定してください。問題が解決するはずです。

0

Ubuntuインストールのオペレーティングシステムレベルでこれを解決するには、以下を確認してください。

$ locale charmap

あなたが取得する場合

locale: Cannot set LC_CTYPE to default locale: No such file or directory

の代わりに

UTF-8

それからLC_CTYPELC_ALLを次のように設定します。

$ export LC_ALL="en_US.UTF-8"
$ export LC_CTYPE="en_US.UTF-8"
0
vervas