我正在unicodes
这里有一个插图:
$ 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
会在这张图片中发挥作用?
答案 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和其他编解码器的工作原理,我强烈建议您阅读: