Python
中大字节概念主要涉及到Python 2.X
中的bytearray
和Python 3.X
中的bytes
。两者中包含的各个元素不是单个字符(Python 2.X中str),而是一个介于0到255之间的整数。当对它使用坐标访问时(例如:my_byte[0])返回的是一个整数,而对它使用切片访问时(例如my_byte[:1])返回的是长度为一的bytes
对象。
>>> cafe = bytes('café', encoding='utf_8')
>>> cafe
b'caf\xc3\xa9'
>>> cafe[0]
99
>>> cafe[:1]
b'c'
>>> cafe_arr = bytearray(cafe)
>>> cafe_arr
bytearray(b'caf\xc3\xa9')
>>> cafe_arr[-1:]
bytearray(b'\xa9')
>>> cafe_arr[-1]
169
UnicodeEncodeError
多数非 UTF 编解码器只能处理 Unicode 字符的一小部分子集。把文本转换成字节序列时,如果目标编码中没有定义某个字符,那就会抛出 UnicodeEncodeError 异常,除非把 errors参数传给编码方法或函数,对错误进行特殊处理。简单来说,大多数编码集都是Unicode的子集,只包含了Unicode中一部分字符。当有Unicode中包含,而目标字符集不包含的字符出现时,就会抛出这种错误。
>>> city = 'São Paulo'
>>> city.encode('utf_8')
b'S\xc3\xa3o Paulo'
>>> city.encode('utf_16')
b'\xff\xfeS\x00\xe3\x00o\x00 \x00P\x00a\x00u\x00l\x00o\x00'
>>> city.encode('iso8859_1')
b'S\xe3o Paulo'
>>> city.encode('cp437')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../lib/python3.4/encodings/cp437.py", line 12, in encode
return codecs.charmap_encode(input,errors,encoding_map)
UnicodeEncodeError: 'charmap' codec can't encode character '\xe3' in
position 1: character maps to <undefined>
>>> city.encode('cp437', errors='ignore')
b'So Paulo'
>>> city.encode('cp437', errors='replace')
b'S?o Paulo'
>>> city.encode('cp437', errors='xmlcharrefreplace')
b'São Paulo'
其中,错误处理方法除了上面列出来的“ignore”,“replace”,“xmlcharrefreplace”之外,还可以自定义错误处理方法,通过codecs.register_error来注册。
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 "<stdin>", line 1, in <module>
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5:
invalid continuation byte
>>> octets.decode('utf_8', errors='replace')
'Montr�al'
BOM
不难发现,UTF-16字符开头经常会出现 b'\xff\xfe'的字符。它叫做BOM,即字节序标记(byte-order mark)。
由于不同平台所依赖的默认编码不同,所以在读写文件时,应该在打开文件时显式指定encoding
值。
网友评论