2

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

>>> 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 具有相同的值,为什么不能都编码?

我必须使用在表单上返回 unicode 数据的外部 API a1,这使得它毫无用处。Python 显然坚持<str>键入的字符串必须只包含 ASCII 字符,否则它拒绝对它们进行编码。它完全破坏了我的应用程序。

4

4 回答 4

3

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

于 2017-04-23T20:38:40.637 回答
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'

python2u前缀一起使用的原因是因为您明确声明“这是一个 Unicode 字符串”。


可能值得阅读以更深入地了解在以下环境中使用 Unicode python2


要使用(损坏的)API,最好将返回的字符串转换为字节数组,但请注意,这在python3.

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

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

于 2017-04-23T20:46:23.387 回答
0

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

我从 Python2.7 curses 模块获取数据。我最好的猜测是问题出在某个地方。终端的编码是 utf-8,但现在可以了。

于 2017-04-23T23:46:45.940 回答
0

让我把你的困惑撕碎。str让我们首先从和的区别开始unicode。在 Python 2.X 中:

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

二、编码方式根据Python文档

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

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

于 2017-04-23T21:00:52.177 回答