web-dev-qa-db-ja.com

readlines()メソッドを使用したPython3 UnicodeDecodeError

行を読み取って投稿するTwitterボットを作成しようとしています。 Python3とtweepyを使用して、共有サーバースペースのvirtualenv経由で。これは、問題があると思われるコードの一部です。

_#!/foo/env/bin/python3

import re
import tweepy, time, sys

argfile = str(sys.argv[1])

filename=open(argfile, 'r')
f=filename.readlines()
filename.close()
_

これは私が得るエラーです:

_UnicodeDecodeError: 'ascii' codec can't decode byte 0xfe in position 0: ordinal not in range(128)
_

エラーは、エラーのソースとしてf=filename.readlines()を明確に指します。何が間違っているのでしょうか?ありがとう。

15
r_e_cur

(Python 3)での最良の答えはerrors=パラメーター:

with open('evil_unicode.txt', 'r', errors='replace') as f:
    lines = f.readlines()

証明:

>>> s = b'\xe5abc\nline2\nline3'
>>> with open('evil_unicode.txt','wb') as f:
...     f.write(s)
...
16
>>> with open('evil_unicode.txt', 'r') as f:
...     lines = f.readlines()
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/codecs.py", line 319, in decode
    (result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe5 in position 0: invalid continuation byte
>>> with open('evil_unicode.txt', 'r', errors='replace') as f:
...     lines = f.readlines()
...
>>> lines
['�abc\n', 'line2\n', 'line3']
>>>

errors=にはreplaceまたはignoreを指定できます。 ignoreは次のようになります。

>>> with open('evil_unicode.txt', 'r', errors='ignore') as f:
...     lines = f.readlines()
...
>>> lines
['abc\n', 'line2\n', 'line3']
23
caleb

デフォルトのエンコードはASCIIのように見えますが、入力はおそらくUTF-8以上です。入力で非ASCIIバイトをヒットすると、例外がスローされます。 readlines自体が問題の原因になるわけではありません。むしろ、read + decodeが発生し、デコードが失敗しています。

ただし、これは簡単な修正です。デフォルトのopen in Python 3は、入力の既知のencodingを提供し、デフォルト(あなたの場合はASCII)を他の認識されたエンコーディングに置き換えます。 。=を提供することにより、Python変換の作業をさせながら、大幅に異なる生のバイナリデータstrオブジェクトではなく)bytesとして読み続けることができます生のディスクバイトから真のテキストデータまで:

# Using with statement closes the file for us without needing to remember to close
# explicitly, and closes even when exceptions occur
with open(argfile, encoding='utf-8') as inf:
    f = inf.readlines()
10
ShadowRanger

自分のための実用的な答えを見つけることになりました:

filename=open(argfile, 'rb')

この投稿 とても助かりました。

0
r_e_cur