15

如果明确定义,以下 unicode 和 string 可以单独存在:

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

如果我只u'Andr\xc3\xa9'分配了一个像上面这样的变量,如何'Andr\xc3\xa9'在 Python 2.5 或 2.6 中将其转换为?

编辑:

我做了以下事情:

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

这解决了我的问题。有人可以向我解释到底发生了什么吗?

4

7 回答 7

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'    

现在它的格式正确。

但是,如果可能,您应该尝试找出数据被错误编码的原因,而不是这样做,并在那里解决该问题。

于 2010-05-06T17:38:39.467 回答
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 通常 [见下面的注释] 是胡说八道;如果幸运的话,它会引发异常;如果你不走运,它会默默地制造胡言乱语。另请理解,默默地创建胡言乱语不是错误——Python(或任何其他语言)无法检测到已提交的废话。这尤其适用于涉及 latin1 的情况,因为所有 256 个代码点都将前 256 个 Unicode 代码点映射为 1 到 1,因此不可能从 str_object.decode('latin1') 获得 UnicodeDecodeError。

当然,异常(人们希望它是异常的)您可能需要按照gibberish_unicode_object.encode('y').decode('x')您的问题的各种答案中的建议来扭转这种废话。

于 2010-05-07T12:48:10.080 回答
4

value_uni.encode('utf8')或您需要的任何编码。

请参阅http://docs.python.org/library/stdtypes.html#str.encode

于 2010-05-06T17:29:38.787 回答
4

如果你有u'Andr\xc3\xa9',那是一个 Unicode 字符串,它是从编码错误的字节字符串中解码出来的。正确的编码是 UTF-8。要将其转换回字节字符串以便正确解码,您可以使用您发现的技巧。Unicode 的前 256 个代码点是使用 ISO-8859-1(别名latin1)编码的 1:1 映射。所以:

>>> 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é
于 2010-05-07T03:43:40.307 回答
1

OP 没有转换为 ascii 或 utf-8。这就是为什么建议的encode方法不起作用的原因。尝试这个:

v = u'Andr\xc3\xa9'
s = ''.join(map(lambda x: chr(ord(x)),v))

业务获取 unicode 字符的chr(ord(x))数值(更适合您的应用程序的一个字节),''.join调用是一种将整数列表转换回普通字符串的习惯用法。毫无疑问,还有一种更优雅的方式。

于 2010-05-06T17:59:51.207 回答
0

简化解释。str 类型只能保存 0-255 范围内的字符。如果您想在 str 中存储 unicode(可以包含范围更广的字符),您首先必须将 unicode 编码为适合 str 的格式,例如 UTF-8。

要在您的 str 对象上执行此调用方法编码,并作为参数提供所需的编码,例如this_is_str = value_uni.encode('utf-8').

您可以在此处阅读有关 Unicode 处理的更长、更深入(且与语言无关)的文章:每个软件开发人员绝对、肯定必须了解 Unicode 和字符集的绝对最低要求(没有借口!)

另一篇优秀的文章(这次是针对 Python 的):Unicode HOWTO

于 2010-05-06T17:36:26.887 回答
-1

这好像是

str(value_uni)

应该工作......至少,当我尝试它时它做到了。

编辑:事实证明,这仅适用于我的系统的默认编码,据我所知,ISO-8859-1 (Latin-1)。因此,对于此平台独立版本,请尝试

value_uni.encode('latin1')
于 2010-05-06T17:27:35.750 回答