第4章 文本和字节序列(上)
4.1 字符问题
Unicode标准把字符的标识和具体的字节表述进行如下区分:
- 字符的标识,即码位,是0~1114111的数字(十进制),在Unicode标准中以4—6个十六进制数标识,而且前缀加“U+”。如字母A的码位是U+0041。
- 字符的具体表述取决于所用的编码。编码是在码位和字节序列之间转换时使用的算法。在UTF-8编码中,A(U+0041)的码位编码成单个字节\x41
将码位转换成字节序列的过程是编码,把字节序列转换成码位的过程是解码。如下例:
>>> b="哈哈哈".encode('utf-8') >>> b b'\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88' >>> b.decode('utf-8') '哈哈哈'
4.2 字节概要
Python内置两种基本二进制序列类型:Python3引入的不可变bytes类型和Python2.6添加的可变bytearray类型。
二者对象的各个元素是介于0-255之间的整数。二进制序列的切片始终是同一类型的二进制序列,包括长度为1的切片。如下所示:
>>> a=bytes('哈哈哈',encoding='utf-8') >>> a b'\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88' >>> a[0] 229 >>> a[:1] b'\xe5' >>> a_arr=bytearray(a) >>> a_arr bytearray(b'\xe5\x93\x88\xe5\x93\x88\xe5\x93\x88') >>> a_arr[-1:] bytearray(b'\x88')
a[0]返回229,a[:1]返回bytes对象切片。
虽然二进制序列其实是整数序列,但是它们的字面量表示法表明其中有ASCII文本。因此,各个字节的值可能会使用如下三种不同的显示方式:
- 可打印的ASCII范围内的字节(从空格到~),使用ASCII字符本身
- 制表符、换行符、回车符和\对应的字节,使用转义序列\t、\n、\r和\
- 其他字节的值,使用十六进制转义序列
结构体和内存视图
struct模块提供了一些函数,可把打包的字节序列转换成不同类型字段组成的元组,还有一些函数用于执行反向转换,把元组转换成打包的字节序列。
struct模块能处理bytes、bytearray和memoryview对象。
4.3 基本的编解码器
*表明该编码不支持表示该字符
典型编码介绍如下:
- latin1:一种重要的编码,是其他编码的基础
- cp1252:Microsoft指定的lantin1超集
- cp437:IBM PC最初的字符集,包含框图符号
- gb2312:用于编码简体中文的陈旧标准
- utf-8:目前Web中最常见的8位编码,与ASCII兼容
- utf-16le:UTF-16的16位编码方案的一种形式
4.4 了解编解码问题
4.4.1 处理UnicodeEncodeError
多数非UTF编解码器只能处理Unicode字符的一小部分子集。把文本转换成字节序列时,如果目标编码中没有定义某个字符,那就会抛出UnicodeEncodeError异常,除非把errors参数传递给编码方法或函数,对错误进行特殊处理。如下例所示:
>>> city="北京" >>> city.encode('utf-8') b'\xe5\x8c\x97\xe4\xba\xac' >>> city.encode('gb2312') b'\xb1\xb1\xbe\xa9' >>> city.encode('cp437') Traceback (most recent call last): File "<pyshell#20>", line 1, in <module> city.encode('cp437') File "G:\Python\lib\encodings\cp437.py", line 12, in encode return codecs.charmap_encode(input,errors,encoding_map) UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-1: character maps to <undefined> >>> city.encode('cp437',errors="ignore") b'' >>> city.encode('cp437',errors='replace') b'??' >>> city.encode('cp437',errors="xmlcharrefreplace") b'北京'
当cp437无法编码汉字时,抛出UnicodeEncodeError。
对error参数的设置说明如下:
- ignore:悄无声息地跳过无法编码的字符串
- replace:将无法编码的字符替换成‘?’
- xmlcharrefreplace:把无法编码的字符替换成XML实体
4.4.2 处理UnicodeDecodeError
不是每一个字节都包含有效的ASCII字符,也不是每一个字符序列都是有效的UTF-8或UTF-16。因此,把二进制序列转换成文本时,如果假设是这两个编码中的一个,遇到无法转换的字节序列时会抛出UnicodeDecodeError。如下例:
>>> octets=b'Montr\xe9al' >>> octets.decode('cp1252') 'Montréal' >>> octets.decode('iso8859_7') 'Montrιal' >>> octets.decode('koi8_r') 'MontrИal' >>> octets.decode('utf-8') Traceback (most recent call last): File "<pyshell#4>", line 1, in <module> octets.decode('utf-8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5: invalid continuation byte >>> octets.decode('utf-8',errors='replace') 'Montr�al'
不同的编解码器将相同的字节解码成不同的字符,对于utf-8解码器,抛出异常。
4.4.3 使用预期之外的编码加载模块时抛出的SyntaxError
Python3默认使用UTF-8编码源码。GNU/Linux和OS X系统大都使用UTF-8编码,因此打开Windows系统中使用cp1252编码的.py文件时可能发生报错。
为修正此问题,可在文件顶部添加一个神奇的coding注释。
# coding: utf-8
python允许在源码中使用非ASCII标识符,这意味着变量名,函数名等可以是中文。
- 流畅的Python 第4章: 文本和字节序列
- 流畅的python第四章文本和字节序列学习记录
- 5.IDA-文本搜索、二进制搜索(16进制字节序列)、替换16进制
- IDA.【转】5.IDA-文本搜索、二进制搜索(16进制字节序列)、替换16进制
- 5.IDA-文本搜索、二进制搜索(16进制字节序列)、替换16进制
- 5.IDA-文本搜索、二进制搜索(16进制字节序列)、替换16进制
- 5.IDA-文本搜索、二进制搜索(16进制字节序列)、替换16进制
- 流程的Python 第四章:文本和字节序列
- Python 文本和字节序列
- xml中1字节的UTF-8序列的字节1无效([字符编码]Invalid byte 1 of 1-byte UTF-8 sequence终极解决方案)
- 【exception】Ant打包xml中1字节的UTF-8序列的字节1无效
- 给定一个非常长的字节序列如何高效的统计1的个数
- 1 字节的 UTF-8 序列的字节 1 无效
- 制作关于图像名称的txt序列文本
- 3 字节的 UTF-8 序列的字节 3 无效。
- com.sun.org.apache.xerces.internal.impl.io.MalformedByteSequenceException: 3 字节的 UTF-8 序列的字节 2 无效 待整理
- Error:Execution failed for task ceException: 1 字节的 UTF-8 序列的字节 1 无
- 在 Perl看来, 字符串只有两种形式. 一种是octets, 即8位序列, 也就是我们通常说的字节数组. 另一种utf8编码的字符串, perl管它叫string. 也就是说: Perl只熟悉两种编
- Java的序列化算法--解释序列后字节含义
- 巧用JAVASCRIPT代码限制文本字节数