为什么你可以' \ xe5'被解码但不是' \ xe5'?

时间:2017-04-23 20:34:11

标签: python unicode-literals

这是令人惊讶的,非常令人沮丧,请帮助。

>>> a1 = '\xe5'   # type <str>
>>> a2 = u'\xe5'  # type <unicode>
>>> ord(a1)
229
>>> ord(a2)
229
>>> print a2.encode('utf-8')
å
>>> print a1.encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

如果a1和a2具有相同的值,为什么不能编码?

我必须使用一个外部API来返回a1表单上的unicode数据,这使得它无用。 Python显然坚持<str>类型的字符串必须只包含ASCII字符,否则它拒绝对它们进行编码。它完全打破了我的申请。

4 个答案:

答案 0 :(得分:3)

您只能编码Unicode字符串。如果你在bytes字符串上调用encode,Python会首先使用默认编码解码它 - 因此错误。 (请注意,这种令人困惑的行为仅发生在Python 2中,已在Python 3中删除。)

答案 1 :(得分:0)

python2中,字符串是ASCII,而python3字符串是Unicode。

ASCII字符的值可能只有0到127之间。 但是,Unicode字符可能具有更高的值。

python2

>>> a = '\x7f'
>>> a.encode('utf-8')
'\x7f'
>>> a = '\x80'
>>> a.encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0x80 in position 0: ordinal not in range(128)

python3

>>> a = '\x7f'
>>> a.encode('utf-8')
b'\x7f'
>>> a = '\x80'
>>> a.encode('utf-8')
b'\xc2\x80'

这在python2中使用u前缀的原因是因为您明确声明&#34; 这是一个Unicode字符串&#34;。

可能值得一读,以便更深入地了解在python2中使用Unicode:

要使用(损坏的)API,最好将返回的字符串转换为bytearray,但是注意,这在python3中不起作用。

>>> a = '\xe5'
>>> b = bytearray(a)
>>> b[0]
229

请记住,\xe5不是有效的Unicode(UTF-8)字符...要将值0xE5存储在UTF-8编码的字符串中,您需要存储两个字节:0xC3 0xA5

答案 2 :(得分:0)

让我把你的困惑撕成碎片。让我们先从strunicode之间的区别开始。在Python 2.X中:

  1. str是一个8位字符(1字节)的字符串,尽可能打印为ASCII。 str实际上是一个字节序列,相当于Python 3.X中的bytes。 * str没有编码。
  2. unicode是一串Unicode代码点。
  3. 其次,编码意味着根据Python documentation

      

    “将Unicode字符串转换为字节序列的规则称为编码。”

    然后,问自己这个问题:编码已经是字节序列的str是否有意义?答案是不。因为str已经是一个字节序列。然而编码unicode确实有意义,为什么?因为它是一串Unicode字符代码点(即U + 00E4')。

答案 3 :(得分:0)

Ignacio建议从其实际编码中解码字节字符串(不是ascii,但是是什么?)让我尝试使用latin-1,即使我认为它应该是utf-8。那很有效!

我从Python2.7 curses模块获取数据。我最好的猜测是问题就在那里。终端的编码是utf-8,但现在可以正常工作。