python高级(四)—— 文本和字节序列(编码问题)
程序员文章站
2024-01-14 08:35:40
本文主要内容 字符 字节 结构体和内存视图 字符和字节之间的转换——编解码器 BOM鬼符 明天继续。。。 python高级——目录 文中代码均放在github上:https://github.com/ampeeg/cnblogs/tree/master/python高级 字符 此时只用记住在pyth ......
本文主要内容
字符
字节
结构体和内存视图
字符和字节之间的转换——编解码器
BOM鬼符
明天继续。。。
文中代码均放在github上:https://github.com/ampeeg/cnblogs/tree/master/python高级
字符
''' 字符编码问题是经常困扰python编程人员的问题,我在编写爬虫的过程中也经常遇到这个头疼的事。 从python3开始,明确区分了人类语言(文本字符串)和机器语言(二进制字节),咱们先说文本字符串 开始之前,得对"字符"进行定义: 字符:Unicode字符,从python3的str对象中获取的元素是Unicode字符 字符串:字符串就是一个字符序列(这里对于(一)中内容相呼应) ''' if __name__ == "__main__": # 创建字符 s1 = str('a') s2 = 'b' s3 = u'c' print(s1, s2, s3) # a b c |
此时只用记住在python3中字符就是unicode,也就是str是unicode,这是人类能够看懂的语言。
字节
''' python3中内置有两种基本的二进制序列类型:不可变的bytes和可变bytearray (1)bytes和bytearray的各个元素是介于0~255(8个bit)之间的整数; (2)二进制序列的切片始终是同一类型的二进制序列 ''' if __name__ == "__main__": # 创建bytes 和 bytearray b1 = bytes('abc你好', encoding='utf8') # 关于encode稍后会说,不知道有没有人和我一样总是将编码与解码的方向混淆 print(b1) # b'abc\xe4\xbd\xa0\xe5\xa5\xbd' b2 = bytearray('abc你好', encoding='utf8') print(b2) # bytearray(b'abc\xe4\xbd\xa0\xe5\xa5\xbd') # 切片(提示:序列都可以切片) print(b1[3:5]) # b'\xe4\xbd' print(b2[3:5]) # bytearray(b'\xe4\xbd') # 使用列表取值的方法试试 print(b1[3]) # 228 此时取出来的就不是字节序列了,而是一个元素 for _ in b1: print(_, end=',') # 97,98,99,228,189,160,229,165,189, 这都是8bit的整数 # bytes的不可变 vs. bytearray的可变 # b1[3] = 160 # 报错:'bytes' object does not support item assignment print(id(b2), b2) # 4373768376 bytearray(b'abc\xe4\xbd\xa0\xe5\xa5\xbd') b2[2] = 78 print(id(b2), b2) # 4373768376 bytearray(b'abN\xe4\xbd\xa0\xe5\xa5\xbd') # 将b2转换成字符串看看 print(b2.decode('utf8')) # abN你好 # 注意,这里之所以能够用utf8转成unicode,是因为N的ascii码和utf8一致 b2.extend(bytearray('添加的内容', encoding='utf8')) # 既然是可变序列,bytearray当然拥有一般的序列的方法 print(id(b2), b2) # 4373768376 bytearray(b'abN\xe4\xbd\xa0\xe5\xa5\xbd\xe6\xb7\xbb\xe5\x8a\xa0\xe7\x9a\x84\xe5\x86\x85\xe5\xae\xb9') print(b2.decode('utf8')) # abN你好添加的内容 # PS:大家可以将二进制序列当成列表,元素就是ascii编码(0~255) |
结构体和内存视图
''' struct可以从二进制序列中提取结构化信息。 struct模块提供了一些函数,可以将打包的字节序列转换成不同类型字段组成的元组;还有一些函数用于执行反向转换。 struct模块可以处理bytes、bytearray、memoryview对象。 ''' import struct if __name__ == "__main__": # memoryview类用于共享内存,可以访问其他二进制序列、打包的数组和缓冲中的数据切片,该操作无需赋值字节序列 fmt = '<3s3sHH' # 设置格式,< 是小字节序,3s3s是两个3字节序列,HH是两个16位二进制整数 with open('L3_图_python.jpg', 'rb') as f: img = memoryview(f.read()) print(bytes(img[:10])) # b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x02\x00\x1c\x00\x1c\x00\x00' print(struct.unpack(fmt, img[:10])) # (b'\xff\xd8\xff', b'\xe0\x00\x10', 17994, 17993) :拆包 del img |
字符和字节之间的转换——编解码器
''' python自带有超过100中编解码器,用于在字符串和字节之间相互转换。 每个编码都有多个名称,例如'utf_8'、'utf8'、'utf-8'、'U8',这些都可以传递给open()、str.encode()、bytes.decode()中的 encoding参数 ''' if __name__ == "__main__": # 看看不同的编码效果 for codec in ['gbk', 'utf8', 'utf16']: print(codec, "你好".encode(codec), sep='\t') ''' gbk b'\xc4\xe3\xba\xc3' utf8 b'\xe4\xbd\xa0\xe5\xa5\xbd' utf16 b'\xff\xfe`O}Y' ''' # 咱们再来解码 print(b'\xc4\xe3\xba\xc3'.decode('gbk')) # 你好 print(b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode('utf8')) # 你好 print(b'\xff\xfe`O}Y'.decode('utf16')) # 你好 |
''' 遇到编码问题一般很烦躁,下面来看看一般怎么解决编码问题。 (1)UnicodeEncodeError (2) UnicodeDecodeError ''' if __name__ == "__main__": # (1)UnicodeEncodeError # 使用errors参数 s1 = "hello,你长胖啦".encode('latin-1', errors='ignore') print(s1) # b'hello' 使用 errors='ignore' 忽略了无法编码的字符 s2 = "hello,你长胖啦".encode('latin-1', errors='replace') print(s2) # b'hello?????' 使用errors='replace'将无法编码的字符用问好代替 s3 = "hello,你长胖啦".encode('latin-1', errors='xmlcharrefreplace') print(s3) # b'hello,你长胖啦' 使用errors='xmlcharrefreplace'将无法编码的内容替换成XML实体 # (2) UnicodeDecodeError # 乱码字符称为鬼符,以下实例演示出现鬼符的情况 s4 = b'Montr\xe9al' print(s4.decode('cp1252')) # Montréal print(s4.decode('iso8859_7')) # Montrιal print(s4.decode('koi8_r')) # MontrИal #print(s4.decode('utf8')) # 报错:UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe9 in position 5: invalid continuation byte print(s4.decode('utf8', errors='replace')) # Montr�al |
明天继续。。。
python高级系列文章目录
上一篇: linux下安装软件