web-dev-qa-db-ja.com

UnicodeDecodeError: 'utf8'コーデックはバイト0x9cをデコードできません

クライアントからUTF-8の有効文字を受け取ることになっているソケットサーバーがあります。

問題は、一部のクライアント(主にハッカー)がそれを介してすべての間違った種類のデータを送信していることです。

本物のクライアントを簡単に見分けることができますが、後で分析できるように、送信されたすべてのデータをファイルに記録しています。

UnicodeDecodeErrorエラーの原因となるこのœのような文字が表示されることがあります。

これらの文字の有無にかかわらず、文字列をUTF-8にできるようにする必要があります。


更新:

私の特定のケースでは、ソケットサービスはMTAだったので、以下のようなASCIIコマンドのみを受け取ることを期待しています。

EHLO example.com
MAIL FROM: <[email protected]>
...

これらすべてをJSONに記録しました。

それから善意なしにそこにいる何人かの人々はあらゆる種類のがらくたを売ることにしました。

私の特定のケースでは、ASCII以外の文字を削除してもまったく問題ないのはそのためです。

222
transilvlad

http://docs.python.org/howto/unicode.html#the-unicode-type

str = unicode(str, errors='replace')

または

str = unicode(str, errors='ignore')

注: これにより、問題の文字が取り除かれ(無視されて)、文字なしで文字列が返されます

私にとっては、私のアプリケーションでは許可されていない非ASCII入力に対する保護として使用しているので、これは理想的なケースです。

あるいは: codecs モジュールからopenメソッドを使ってファイルを読み込む:

import codecs
with codecs.open(file_name, 'r', encoding='utf-8',
                 errors='ignore') as fdata:
288
transilvlad

私がPython 3に移行した今、この種の問題は私のために生じています。Python2が単にSteamがファイルエンコーディングに関する問題を巻き込んでいることを私は知らなかった。

私は違いについてのこの素晴らしい説明と、上記のどれもが私のために働かなかった後に解決策を見つける方法を見つけました。

http://python-notes.curiousefficiency.org/en/latest/python3/text_file_processing.html

つまり、Python 3をPython 2とできるだけ同じように動作させるには、次のようにします。

with open(filename, encoding="latin-1") as datafile:
    # work on datafile here

しかし、記事を読んで、すべての解決策に適合するサイズはありません。

47
James McCormac

エンジンをCからPythonに変更することが私にとってのトリックでした。

エンジンはCです:

pd.read_csv(gdp_path, sep='\t', engine='c')

'utf-8'コーデックは位置18のバイト0x92をデコードできません:開始バイトが無効です

エンジンはPythonです。

pd.read_csv(gdp_path, sep='\t', engine='python')

私にはエラーはありません。

43
Doğuş Bıçak
>>> '\x9c'.decode('cp1252')
u'\u0153'
>>> print '\x9c'.decode('cp1252')
œ

私はUnicodeDecodeErrorと同じ問題を抱えていました、そして私はこの行でそれを解決しました。最善の方法であるかどうかわからないが、それは私のために働いた。

str = str.decode('unicode_escape').encode('utf-8')
16
maiky_forrester

念のために誰かが同じ問題を抱えている。 YouCompleteMe でvimを使用していますが、このエラーメッセージが表示されてycmdを起動できませんでした。export LC_CTYPE="en_US.UTF-8"、問題は解決しました。

2
hylepo

ファイルを変更する必要があるが、ファイルのエンコーディングがわからない場合はどうすればよいですか。エンコーディングがASCII互換であり、ASCIIの部分だけを調べたり変更したい場合は、surrogateescapeエラーハンドラを使ってファイルを開くことができます。

with open(fname, 'r', encoding="ascii", errors="surrogateescape") as f:
    data = f.read()

1つ目は、get_encoding_typeを使用してファイルタイプのエンコードを取得する方法です。

import os    
from chardet import detect

# get file encoding type
def get_encoding_type(file):
    with open(file, 'rb') as f:
        rawdata = f.read()
    return detect(rawdata)['encoding']

次に、次の種類のファイルを開きます。

open(current_file, 'r', encoding = get_encoding_type, errors='ignore')
0
Ivan Lee