2022-01-28 20:31:29
Python的struct模块中的pack()和unpack()函数通过格式字符串定义数据类型和字节序,可高效解析和生成二进制数据,适用于二进制文件处理、网络通信及数据转换等场景。
1. 核心功能解析pack()函数:将Python值按指定格式转换为字节字符串。
语法:struct.pack(fmt, v1, v2, ...)
参数:
fmt:格式字符串,定义数据类型(如整数、浮点数)和字节序(如小端序<、大端序>)。
v1, v2, ...:待打包的Python值,数量需与fmt中定义的字段数一致。
示例:import structa, b = 1, 65536packed_data = struct.pack('<ii', a, b) # 小端序,两个整数print(packed_data) # 输出:b'x01x00x00x00x00x01x00x00'
unpack()函数:将字节字符串按指定格式解析为Python值。
语法:struct.unpack(fmt, data)
参数:
fmt:与pack()相同的格式字符串。
data:待解包的字节字符串,长度需与fmt定义的字节数匹配。
示例:import structdata = b'x01x02x03x04'unpacked_data = struct.unpack('<ii', data) # 小端序,两个整数print(unpacked_data) # 输出:(513, 1027)(0x0201=513,0x0403=1027)
格式字符串由以下部分组成:
<:小端序(低位在前)。
>:大端序(高位在前)。
=:系统原生字节序(默认)。
i:4字节有符号整数。
I:4字节无符号整数。
h:2字节有符号整数。
H:2字节无符号整数。
f:4字节浮点数。
d:8字节双精度浮点数。
s:字节串(需指定长度,如5s表示5字节)。
可在类型前加数字表示重复次数,如3i表示3个整数。
示例:
import struct# 打包:1个无符号短整型 + 2个浮点数(小端序)packed = struct.pack('<Hff', 100, 3.14, 2.71)print(packed) # 输出:b'dx00xcdxccx8c@xaeGxe1?'# 解包:需与打包格式一致unpacked = struct.unpack('<Hff', packed)print(unpacked) # 输出:(100, 3.140000104904175, 2.7100000381469727)3. 高效应用场景二进制文件解析:读取传感器数据、图像文件(如BMP头信息)等结构化数据。示例:解析BMP文件头(前14字节):
import structbmp_header = b'BM...x36x00x00x00...' # 模拟BMP头fmt = '<2sIHH' # 2字节标识+4字节文件大小+2字节保留+2字节偏移file_type, size, reserved, offset = struct.unpack(fmt, bmp_header[:10])print(f"文件类型: {file_type.decode()}, 大小: {size}字节")网络通信:处理TCP/UDP数据包时,需按协议规范解析二进制头部。示例:解析IP数据包头部(简化版):
ip_header = b'x45x00x00x54x00x00x40x00...' # 模拟IP头fmt = '>BBHHHBBH' # 大端序:版本+IHL+服务类型+总长度+标识+标志+片偏移+TTL+协议+校验和version_ihl, _, total_length, _, _, _, ttl, _ = struct.unpack(fmt, ip_header[:12])print(f"总长度: {total_length}字节, TTL: {ttl}")数据转换与存储:跨平台数据交换时统一字节序(如小端序存储)。示例:将数据转为小端序字节串并写入文件:
data = (1, 2.5, 300)packed = struct.pack('<ifI', *data) # 小端序:整数+浮点数+无符号整数with open('data.bin', 'wb') as f: f.write(packed)复用Struct对象:频繁调用pack()/unpack()时,先用struct.Struct(fmt)创建预编译对象,提升效率。示例:
import structfmt = '<ii'packer = struct.Struct(fmt)packed = packer.pack(1, 2) # 复用packer对象批量处理数据:对大量数据分块处理,避免一次性操作内存不足。
错误处理:检查字节字符串长度是否匹配格式字符串定义的字节数,否则会触发struct.error。
通过合理使用struct模块的pack()和unpack()函数,可高效、可靠地处理二进制数据,满足底层编程需求。