Python中的Latin-1和Unicode有什么区别?

6
我正在阅读 SO 上关于 Unicode 的高评分帖子
这里有一个在帖子中给出的示例:
$ 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表示字符“é”,因此这就是终端显示的内容。

我的问题是:当编码为'UTF-8'时,为什么终端要匹配Latin-1字符映射?

当我尝试运行以下命令时:

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

我对第一个结果得到了与上面描述不同的结果。为什么会有这种差异?`latin-1` 又在这个过程中扮演了什么角色?

我不确定原帖作者是如何得到那个输出的,但那是错误的,除非原帖作者更改了 sys.stdout.encoding 的值。 - Martijn Pieters
1个回答

7
你缺少一些重要的上下文信息;在这种情况下,OP 配置了终端模拟器(Gnome Terminal)以 Latin-1 解释输出,但将 shell 变量设置为 UTF-8。因此,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替换字符标志

>>> '\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是Unicode码点U+9000到U+9FFF的3字节编码的起始字节,如果作为单个字节打印就是无效的。下面的代码是正确的:

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

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

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


那么为什么'xe9'u'\xe9'打印出来不同,以及latin-1unicode之间的区别,因为它们中的一个使用一个字节,而另一个使用两个字节?(从那篇帖子中我模糊地理解到) - eagertoLearn
@user1988876:?只是U+003F,或者作为UTF-8、Latin1或ASCII字节的\x3f - Martijn Pieters
2
@user1988876:在UTF-8中,范围在00-7F之外的任何单字节都是无效的。在U+007F之后,所有代码点都需要至少2个字节来编码。 - Martijn Pieters
@MartijnPieters:感谢您指出。那是否意味着它在UTF-16中有效? - brain storm
@MartijnPieters:我知道E91110 1001,但我不明白它如何以3个位设置开始,其中一个位未被设置。 - eagertoLearn
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接