如何在Python中将unicode转换为字符串?

15 投票
7 回答
51127 浏览
提问于 2025-04-15 22:26

以下的unicode和字符串如果明确地定义,可以单独存在:

>>> value_str='Andr\xc3\xa9'
>>> value_uni=u'Andr\xc3\xa9'

如果我只有像上面那样把 u'Andr\xc3\xa9' 赋值给一个变量,我该如何在Python 2.5或2.6中将其转换为 'Andr\xc3\xa9' 呢?

编辑:

我做了以下操作:

>>> value_uni.encode('latin-1')
'Andr\xc3\xa9'

这解决了我的问题。有人能给我解释一下到底发生了什么吗?

7 个回答

5

你在评论中问:“这让我很困惑。它是怎么从最初的带重音字符变成现在这样的?当你说用utf8和latin1进行了双重编码时,是不是总共编码了3次(2次utf8 + 1次latin1)?从原始状态到现在的编码顺序是什么?”

在Mark Byers的回答中,他提到:“你所拥有的似乎是一个被错误解码的UTF-8编码。”你接受了他的回答,但还是觉得困惑?好吧,下面我会详细解释一下:

注意:所有字符串将使用(隐式地)repr()显示。unicodedata.name()将用于验证内容。这样,控制台编码的变化就不会影响字符串的解释。

初始状态:你有一个名为u1的unicode对象。它包含了e-acute字符:

>>> u1 = u'\xe9'
>>> import unicodedata as ucd
>>> ucd.name(u1)
'LATIN SMALL LETTER E WITH ACUTE'

你将u1编码为UTF-8,并将结果命名为s:

>>> s = u1.encode('utf8')
>>> s
'\xc3\xa9'

你用latin1解码s——这是错误的;s是用utf8编码的,而不是latin1。结果就是一些毫无意义的垃圾。

>>> u2 = s.decode('latin1')
>>> u2
u'\xc3\xa9'
>>> ucd.name(u2[0]); ucd.name(u2[1])
'LATIN CAPITAL LETTER A WITH TILDE'
'COPYRIGHT SIGN'
>>>

请理解:unicode_object.encode('x').decode('y')当x和y不同时,通常是没有意义的;如果你运气好,它会抛出异常;如果运气不好,它会默默地生成一些无意义的东西。还要明白,默默生成无意义的东西并不是一个bug——没有通用的方法可以让Python(或其他语言)检测出这种无意义的情况。这尤其适用于latin1,因为所有256个代码点与前256个Unicode代码点一一对应,所以从str_object.decode('latin1')中不可能得到UnicodeDecodeError。

当然,异常情况下(希望这不是常态),你可能需要通过执行gibberish_unicode_object.encode('y').decode('x')来逆转这种无意义的情况,这在你问题的各种回答中都有提到。

6

如果你有 u'Andr\xc3\xa9' 这个字符串,它是一个Unicode字符串,这个字符串是从一个编码错误的字节字符串解码过来的。正确的编码方式是UTF-8。为了把它转换回字节字符串,这样你就可以正确解码,你可以使用你发现的小技巧。Unicode的前256个编码点和ISO-8859-1(也叫 latin1)编码是一一对应的。所以:

>>> u'Andr\xc3\xa9'.encode('latin1')
'Andr\xc3\xa9'

现在它变成了一个字节字符串,可以用 utf8 正确解码:

>>> 'Andr\xc3\xa9'.decode('utf8')
u'Andr\xe9'
>>> print 'Andr\xc3\xa9'.decode('utf8')
André

一步到位:

>>> print u'Andr\xc3\xa9'.encode('latin1').decode('utf8')
André
16

看起来你在编码上搞混了。你真正想要的可能是 u'Andr\xe9',这和 'André' 是一样的。

但你现在的内容似乎是一个错误解码的UTF-8编码。你可以通过把这个unicode字符串转换成普通字符串来修复它。我不太确定最好的方法是什么,但这个方法似乎有效:

>>> ''.join(chr(ord(c)) for c in u'Andr\xc3\xa9')
'Andr\xc3\xa9'

然后正确解码:

>>> ''.join(chr(ord(c)) for c in u'Andr\xc3\xa9').decode('utf8')
u'Andr\xe9'    

现在它就变成正确的格式了。

不过,如果可以的话,建议你先弄清楚数据为什么会被错误编码,然后在源头解决这个问题。

撰写回答