编码和解码
文本是用字符串来表示的,一个字符串是一个字符(Unicode字符)序列。码位是字符的标识,是0~1114111的数字。例如“A”的码位为“U+0041”(在Unicode 标准中以 4~6 个十六进制数字表示, 而且加前缀“U+”)。字符的具体表述取决于所用的编码,不同的编码标准会将字符(严谨讲是码位)转换成相应的字节序列。解码即是编码的逆向过程,将字节序列转换为码位。
字节
Python内置有两种二进制序列类型:bytes
(字节序列)和bytearray
(字节数组)。
bytes和bytearray对象的各个元素是在0~255之间的整数。bytes和bytearray对象的切片仍然是bytes和bytearray对象。
二进制序列的字面量中也会存在ASCII文本,如b'caf\xc3\xa9
,其中caf
是在可打印的ASCII范围内的字节,显示ASCII字符本身,而后面\xc3\xa9
两个字节不可打,使用十六进制转义序列。
struct
模块提供了一些函数, 把打包的字节序列转换成不同类型字段组成的元组。
编解码器
Python自带了超100种编解码器,用于在文本和字节之间相互转换。
下图展示了不同编码器对相同字符编码的差异。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MKTU87SP-1670811597581)(https://gitee.com/mstifiy/img-load/raw/master/noteImg/image-20221212093521302.png)]
UTF系列编码能处理每一个Unicode 码位。
一些典型编码:
名称 | 描述 |
---|---|
latin1 | 一种重要的编码, 是其他编码的基础。 |
cp1252 | Microsoft 制定的 latin1 超集, 添加了有用的符号, 例如弯引号和€(欧元) |
cp437 | IBM PC 最初的字符集, 包含框图符号。 |
gb2312 | 用于编码简体中文的陈旧标准。 |
utf-8 | Web 中最常见的 8 位编码。 |
utf-16le | UTF-16 的 16 位编码方案的一种形式。 |
编码异常
-
UnicodeEncodeError
把文本转换成字节序列时, 如果目标编码中没有定义某个字符, 那就会抛出
UnicodeEncodeError
异常。解决方法是:把errors
参数传给编码方法或函数, 对错误进行特殊处理。 -
UnicodeDecodeError
把二进制序列转换成文本时, 遇到无法转换的字节序列时会抛出
UnicodeDecodeError
。同样也可以通过设置errors
解决报错问题。 -
SyntaxError
Python 3 默认使用 UTF-8 编码源码。如果加载的 .py 模块中包含 UTF-8 之外的数据, 而且没有声明编码,就会抛出
SyntaxError
。一种解决方法如下:# coding: cp1252 print('Olá, Mundo!')
通过添加coding注释指定源码编码方式。
字节序
UTF-16编码中,在编码结果开头可能会生成几个额外的字节,这几个额外的字节叫做BOM,即字节序标记(byte-order mark)。字节序分为小字节序和大字节序。区别在于,在小字节序CPU和大字节序CPU中,单个字符的编码顺序是相反的,比如'E'
的编码在小字节序CPU中编码为69 0
,而在大字节序CPU中编码为0 69
。
UTF-16有两个变种:UTF-16LE(显示使用小字节序),UTF-16BE(显示使用大字节序)。