如果您尝试将此字符串解码为 utf-8,如您所知,您将收到“UnicodeDecode”错误,因为这些虚假的 cp1252 字符是无效的 utf-8 -
但是,Python 编解码器允许您使用 codecs.register_error 函数注册回调以处理编码/解码错误 - 它获取 UnicodeDecodeerror aa 参数 - 您可以编写这样的处理程序来尝试将数据解码为“cp1252”,并且继续以 utf-8 解码字符串的其余部分。
在我的 utf-8 终端中,我可以构建一个混合的错误字符串,如下所示:
>>> a = u"maçã ".encode("utf-8") + u"maçã ".encode("cp1252")
>>> print a
maçã ma��
>>> a.decode("utf-8")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.6/encodings/utf_8.py", line 16, in decode
return codecs.utf_8_decode(input, errors, True)
UnicodeDecodeError: 'utf8' codec can't decode bytes in position 9-11: invalid data
我在这里写了上述回调函数,发现了一个问题:即使你将解码字符串的位置加 1,这样它就会从下一个字符开始,如果下一个字符也不是 utf-8 并且 out对于范围(128),错误在第一个超出范围(128)字符时引发 - 这意味着,如果发现连续的非 ascii、非 utf-8 字符,则解码“后退”。
这一轮的工作是在error_handler中有一个状态变量,它检测到这个“走回”并从最后一次调用它恢复解码 - 在这个简短的例子中,我将它实现为一个全局变量 - (它必须手动在每次调用解码器之前重置为“-1”):
import codecs
last_position = -1
def mixed_decoder(unicode_error):
global last_position
string = unicode_error[1]
position = unicode_error.start
if position <= last_position:
position = last_position + 1
last_position = position
new_char = string[position].decode("cp1252")
#new_char = u"_"
return new_char, position + 1
codecs.register_error("mixed", mixed_decoder)
在控制台上:
>>> a = u"maçã ".encode("utf-8") + u"maçã ".encode("cp1252")
>>> last_position = -1
>>> print a.decode("utf-8", "mixed")
maçã maçã