在python中双解码unicode

Mor*_*uhr 12 python unicode utf-8

我正在努力反对一个似乎热衷于返回的应用程序,我认为是双UTF-8编码的字符串.

我发送u'XüYß'使用UTF-8编码的字符串,从而变为X\u00fcY\u00df(等于X\xc3\xbcY\xc3\x9f).

服务器应该简单地回显我发送的内容,但返回以下内容:( X\xc3\x83\xc2\xbcY\xc3\x83\xc2\x9f应该是X\xc3\xbcY\xc3\x9f).如果我对其进行解码使用str.decode('utf-8')u'X\xc3\xbcY\xc3\x9f',它看起来像一个......的unicode字符串,使用含UTF-8编码的原始字符串.

但Python不会让我解码unicode字符串而不首先重新编码它 - 由于某种原因失败了,这让我感到厌烦:

>>> ret = 'X\xc3\x83\xc2\xbcY\xc3\x83\xc2\x9f'.decode('utf-8')
>>> ret
u'X\xc3\xbcY\xc3\x9f'
>>> ret.decode('utf-8')
# Throws UnicodeEncodeError: 'ascii' codec can't encode ...
Run Code Online (Sandbox Code Playgroud)

我如何说服Python重新解码字符串?- 和/或是否有任何(实用的)方法来调试字符串中的实际内容,而不通过所有隐式转换print使用它?

(是的,我已经向服务器端的开发人员报告了这种行为.)

小智 23

ret.decode()隐式尝试ret使用系统编码进行编码 - 在您的情况下为ascii.

如果你明确编码unicode字符串,你应该没问题.有一个内置编码,可以满足您的需求:

>>> 'X\xc3\xbcY\xc3\x9f'.encode('raw_unicode_escape').decode('utf-8')
'XüYß'
Run Code Online (Sandbox Code Playgroud)

真的,.encode('latin1')(或cp1252)会没问题,因为这就是服务器几乎不能使用的东西.该raw_unicode_escape编解码器将只是给你的东西识别在最后,而不是抛出一个异常:

>>> '€\xe2\x82\xac'.encode('raw_unicode_escape').decode('utf8')
'\\u20ac€'

>>> '€\xe2\x82\xac'.encode('latin1').decode('utf8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'latin-1' codec can't encode character '\u20ac' in position 0: ordinal not in range(256)
Run Code Online (Sandbox Code Playgroud)

如果您遇到这种混合数据,您可以再次使用编解码器来规范化所有内容:

>>> '€\xe2\x82\xac'.encode('raw_unicode_escape').decode('utf8')
'\\u20ac€'

>>> '\\u20ac€'.encode('raw_unicode_escape')
b'\\u20ac\\u20ac'
>>> '\\u20ac€'.encode('raw_unicode_escape').decode('raw_unicode_escape')
'€€'
Run Code Online (Sandbox Code Playgroud)