理解decode()和encode()unicode

时间:2015-01-28 20:17:02

标签: python python-2.7 unicode encoding

我无法了解函数decode()encode()如何在python2.7上运行

我尝试了以下声明

>>> s = u'abcd'
>>> s.encode('utf8')
'abcd'
>>> s.encode('utf16')
'\xff\xfea\x00b\x00c\x00d\x00'
>>> s.encode('utf32')
'\xff\xfe\x00\x00a\x00\x00\x00b\x00\x00\x00c\x00\x00\x00d\x00\x00\x00'

直到这里,我认为它很清楚; encode()转换相应的utf-8/16/32字节字符串中的unicode代码。

但是当我编码:

>>> s.decode('utf8')
u'abcd'
>>> s.decode('utf16')
u'\u6261\u6463'
>>> s.decode('utf32')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/encodings/utf_32.py", line 11, in decode
    return codecs.utf_32_decode(input, errors, True)
UnicodeDecodeError: 'utf32' codec can't decode bytes in position 0-3: codepoint not in range(0x110000)

为什么decode()在unicode类型上的含义?为什么第一个(使用utf8)而不是后者?是因为python在内部使用utf-8存储unicode字符串吗?

最后一件事:

>>> s2 = '≈'
>>> s2
'\xe2\x89\x88'

引擎盖下会发生什么? &#39;≈&#39;不是ascii字符,python使用编码sys.getfilesystemencoding()返回隐式转换它吗?

1 个答案:

答案 0 :(得分:6)

您正在decode字符串上调用unicode。 Python首先使用默认的ASCII编解码器字符串进行编码,以便您有实际的字节解码。您无法解码Unicode数据本身,已经解码。

然后解码失败,因为字节不是有效的UTF-32数据。 bytestring 'abcd'可解码为UTF-8,因为ASCII是UTF-8的子集。编码为ASCII然后解码为UTF-8产生相同的信息。解码为UTF-16碰巧偶然发挥作用;你提供了4个字节,其中包含十六进制值0x61,0x62,0x63和0x64(字符abcd的ASCII值),这些字节可以解码为\u6261和{{1的UTF-16小端}}。但是UTF-32编码系统中没有对这4个字节进行有效解码。

如果\u6463中包含无法先编码为ASCII的数据,您将获得s个异常;请注意该名称中的 Encode

UnicodeEncodeError

因为对bytestring的隐式编码失败。

在Python 3中,>>> u'åßç'.decode('utf8') Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/encodings/utf_8.py", line 16, in decode return codecs.utf_8_decode(input, errors, True) UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ordinal not in range(128) 个对象已重命名为unicode,并且已从类型中删除str方法以防止此类混淆。仅剩str.decode()。 Python str.encode()类型已被str类型取代,该类型只有bytes方法。

您的第二个示例显示您在终端或控制台中以交互方式使用Python解释器。 Python从终端接收您的输入为UTF-8字节,并将这些字节存储在bytestring中。如果您使用bytes.decode()文字,Python会使用为您的终端声明的编码自动解码这些字节;您可以内省unicode来查看Python检测到的内容:

sys.stdin.encoding

反之亦然,打印时>>> import sys >>> sys.stdin.encoding 'UTF-8' >>> s = '≈' >>> s '\xe2\x89\x88' >>> s = u'≈' >>> s u'\u2248' >>> print s ≈ 编解码器用于将Unicode字符串自动编码为终端使用的编解码器,然后再次解释这些字节以在屏幕上显示正确的字形。

如果您不使用Python交互式解释器,而是使用Python源文件,则使用的编解码器由PEP-263 Python source code encodings declaration确定,因为Python 2默认将字节解码为ASCII。 / p>

sys.stdout.encoding与这一切无关;它告诉你Python认为你的文件系统元数据被编码的内容;例如目录中的文件名。当您使用sys.getfilesystemencoding()路径进行与unicode等文件系统相关的调用时,会使用这些值。