latin-1 vs python中的unicode

时间:2014-02-19 19:18:44

标签: python unicode utf-8 latin1

我正在unicodes

的SO中阅读此high rated post

这里有一个插图:

$ 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'时,为什么终端与latin-1字符映射匹配?

当我尝试

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

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

1 个答案:

答案 0 :(得分:6)

你缺少一些重要的背景;在这种情况下,OP配置终端仿真器(Gnome Terminal)将输出解释为Latin-1,但将shell变量设置为UTF-8。因此,shell告诉Python使用UTF-8进行Unicode输出,但终端的实际配置是期望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中,\xe9是3字节编码的起始字节,对于Unicode代码点U + 9000到U + 9FFF,如果打印为单个字节则无效。这有效:

>>> print '\xe9\x80\x80'
退

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

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