您已经拥有 UTF-8 编码的数据。在您的字节串中没有要转义的字符串文字字符。您正在查看字符串的 repr() 输出,其中不可打印的 ASCII 字符显示为转义序列,因为这使得该值可以轻松地以 ASCII 安全的方式复制粘贴。您看到的\xc3 是一个字节,而不是单独的字符:
>>> 'Erd\xC3\xA4pfel'
'Erd\xc3\xa4pfel'
>>> 'Erd\xC3\xA4pfel'[3]
'\xc3'
>>> 'Erd\xC3\xA4pfel'[4]
'\xa4'
>>> print 'Erd\xC3\xA4pfel'
Erdäpfel
您必须使用原始字符串文字或双反斜杠才能真正获得unicode-escape 可以处理的转义序列:
>>> '\\xc3\\xa4'
'\\xc3\\xa4'
>>> '\\xc3\\xa4'[0]
'\\'
>>> '\\xc3\\xa4'[1]
'x'
>>> '\\xc3\\xa4'[2]
'c'
>>> '\\xc3\\xa4'[3]
'3'
>>> print '\\xc3\\xa4'
\xc3\xa4
注意该字符串中如何有一个单独的\ 反斜杠字符(回显为\\,再次转义)。
在解释实际转义序列之后,unicode-escape 将您的数据解码为 Latin-1,因此您最终会得到一个包含字符 U+00C3 LATIN CAPITAL LETTER A WITH TILDE 的 Unicode 字符串。将其编码回 Latin-1 字节会再次为您提供 \xC3 字节,然后您将返回 UTF-8 字节。然后解码为 UTF-8 正常工作。
但您的第二次尝试将带有 TILDE 代码点的 U+00C3 拉丁大写字母 A 编码为 UTF-8,而 编码为您提供了字节序列 \xc3\x83。将这些字节打印到 UTF-8 终端将显示 Ã 字符。另一个字节\xA4 变成了U+00A4 CURRENCY SIGN,其UTF-8 字节序列为\xc2\xa4,打印为¤。
这里完全不需要解码为unicode-escape。让数据保持原样。或者,也许,解码为 UTF-8 以获得 unicode 对象:
>>> 'Erd\xC3\xA4pfel'.decode('utf8')
u'Erd\xe4pfel'
>>> print 'Erd\xC3\xA4pfel'.decode('utf8')
Erdäpfel
如果您的实际数据(而不是您所做的测试)包含编码 UTTF-8 的\xhh 转义序列,则不要使用unicode-escape 解码这些序列 。使用string-escape,这样您就可以得到一个包含 UTF-8 数据的字节字符串(然后您可以根据需要将其解码为 Unicode):
>>> 'Erd\\xc3\\xa4pfel'
'Erd\\xc3\\xa4pfel'
>>> 'Erd\\xc3\\xa4pfel'.decode('string-escape')
'Erd\xc3\xa4pfel'
>>> 'Erd\\xc3\\xa4pfel'.decode('string-escape').decode('utf8')
u'Erd\xe4pfel'
>>> print 'Erd\\xc3\\xa4pfel'.decode('string-escape').decode('utf8')
Erdäpfel