latin-1 vs unicode in python



我在unicodes上阅读了SO中的这篇高评价帖子

这里有一个例子:

$ python
>>> import sys
>>> print sys.stdout.encoding
UTF-8
>>> print 'xe9' # (1)
é
>>> print u'xe9' # (2)
é
>>> print u'xe9'.encode('latin-1') # (3)
é
>>>

并且解释为

(1)python按原样输出二进制字符串,终端接收它并尝试将其值与latin-1字符映射匹配。在latin-1中,0xe9或233产生字符"é",因此这就是终端显示的内容。

我的问题是:当encoding'UTF-8'时,为什么终端与拉丁-1字符映射匹配?

当我尝试时

>>> print 'xe9'
?
>>> print u'xe9'
é

我得到的第一个结果与上面描述的不同。为什么会出现这种差异,latin-1在这张照片中的作用在哪里?

您缺少一些重要的上下文;在这种情况下,OP将终端模拟器(Gnome终端)配置为将输出解释为Latin-1,但将shell变量设置为UTF-8。因此,shell告诉Python对Unicode输出使用UTF-8,但终端的实际配置是预期的Latin-1字节。

print输出清楚地表明终端正在使用Latin-1解释输出,并且而不是使用UTF-8。

当终端设置为UTF-8时,xe9字节不是有效的(不完整的)UTF-8,您的终端通常会打印一个问号:

>>> import sys
>>> sys.stdout.encoding
'UTF-8'
>>> print 'xe9'
?
>>> print u'xe9'
é
>>> print u'xe9'.encode('utf8')
é

如果您指示Python忽略这些错误,它会给您提供U+FFFD REPLACEMENT CHARACTER字形

>>> 'xe9'.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)
UnicodeDecodeError: 'utf8' codec can't decode byte 0xe9 in position 0: unexpected end of data
>>> 'xe9'.decode('utf8', 'replace')
u'ufffd'
>>> print 'xe9'.decode('utf8', 'replace')
�

这是因为在UTF-8中,对于Unicode代码点U+9000到U+9FFF,xe9是3字节编码的起始字节,如果仅打印为单个字节,则无效。这项工作:

>>> print 'xe9x80x80'
退

因为这是U+9000代码点的UTF-8编码,一个CJK象形文字字形。

如果你想了解编码和Unicode之间的区别,以及UTF-8和其他编解码器是如何工作的,我强烈建议你阅读:

  • Joel Spolsky 的绝对最小值每个软件开发人员绝对、积极地必须知道Unicode和字符集(没有借口!)

  • Python Unicode HOWTO

  • Ned Batchelder 的实用Unicode

最新更新