我有一个需要逐行检查的日志文件,显然它包含一些“坏字节”。我收到一条错误消息,大致如下:
UnicodeDecodeError:“utf-8”编解码器无法解码位置9中的字节0xb0:无效的起始字节
我已经能够将问题分解为包含以下行的文件“log.test”:
Message: \260
(至少这是它在我的emacs中的显示方式。)
我有一个文件“demo_error.py”,看起来是这样的:
import sys
with open(sys.argv[1], 'r') as lf:
for i, l in enumerate(lf):
print(i, l.strip())
然后从命令行运行:
$python3 demo_error.py日志.test
完整的回溯是:
Traceback (most recent call last):
File "demo_error.py", line 5, in <module>
for i, l in enumerate(lf):
File "/usr/local/Cellar/python3/3.4.0/Frameworks/Python.framework/Versions/3.4/lib/python3.4/codecs.py", line 313, in decode
(result, consumed) = self._buffer_decode(data, self.errors, final)
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb0 in position 13: invalid start byte
我的直觉是,我必须以某种方式指定一个更通用的编解码器(例如“raw ascii”),但我不太确定如何做到这一点。
注意,这在Python2.7中并不是一个真正的问题。
为了明确我的观点:我不介意对所讨论的行有一个例外——然后我可以简单地放弃该行。问题是,异常似乎发生在“for”循环本身上,这使得无法对该特定行进行特殊处理。
最佳答案
您也可以使用codecs模块。使用codecs.open()函数时,可以使用errors参数指定它如何处理错误:
codecs.open(filename, mode[, encoding[, errors[, buffering]]])
errors参数可以是几个不同的关键字之一,这些关键字指定当python试图解码对当前编码无效的字符时,您希望python的行为方式。您可能对codecs.ignore_errors或codecs.replace_errors最感兴趣,这将分别导致忽略无效字符或替换为默认字符。
如果知道有损坏的数据,即使指定了正确的编码,也会导致unicodedecodeerror出现,则此方法是一个很好的替代方法。
例子:
with codecs.open('file.txt', mode='r', errors='ignore'):
# ...stuff...
# Even if there is corrupt data and invalid characters for the default
# encoding, this open() will still succeed