今天来分享这个"神奇"的struct库,它能让你轻松处理各种二进制文件。
struct库到底是干什么的?
简单说,struct库就是Python和二进制数据之间的"翻译官"。
你知道吗?计算机里的所有文件,不管是图片、音频、视频还是游戏存档,本质上都是一堆0和1组成的二进制数据。而struct库就能帮我们把这些看不懂的二进制数据,转换成我们能理解的数字、字符串等。
反过来,它也能把我们的数据"打包"成二进制格式保存到文件里。
基础用法:pack和unpack
1. 打包数据(pack)
import struct
data = struct.pack('if', 1234, 3.14)
print(data)
print(len(data))
这里的'if'是格式字符串:
'i' 表示一个4字节的整数
'f' 表示一个4字节的浮点数
2. 解包数据(unpack)
import struct
binary_data = b'\xd2\x04\x00\x00\xc3\xf5H@'
num, pi = struct.unpack('if', binary_data)
print(f"整数: {num}")
print(f"浮点数: {pi}")
实战应用:读取BMP图片的基本信息
想知道一张BMP图片的宽度和高度吗?用struct库几行代码就搞定:
import struct
def read_bmp_info(filename):
with open(filename, 'rb') as f:
header = f.read(54)
if header[:2] != b'BM':
print("这不是BMP文件!"
)
return
width, height = struct.unpack(', header[18:26])
print(f"图片宽度: {width} 像素")
print(f"图片高度: {height} 像素")
注意:
中的 <
表示小端字节序,I
表示无符号整数。
解析网络数据包
如果你对网络编程感兴趣,struct在解析网络协议时特别有用:
import struct
def parse_ip_header(packet_data):
ip_header = struct.unpack('!BBHHHBBH4s4s', packet_data[:20])
version = ip_header[0] >> 4
protocol = ip_header[6]
src_ip = ip_header[8]
dst_ip = ip_header[9]
print(f"IP版本: {version}")
print(f"协议: {protocol}")
import socket
src_ip_str = socket.inet_ntoa(src_ip)
dst_ip_str = socket.inet_ntoa(dst_ip)
print(f"源IP: {src_ip_str}")
print(f"目标IP: {dst_ip_str}")
处理传感器数据
假设你有一个温湿度传感器,每次发送8字节的数据:
import struct
import time
def simulate_sensor_data():
"""模拟传感器发送的二进制数据"""
temperature = 25.6
humidity = 60.3
timestamp = int(time.time())
data = struct.pack('ffi', temperature, humidity, timestamp)
return data
def parse_sensor_data(binary_data):
"""解析传感器数据"""
temp, humid, ts = struct.unpack('ffi', binary_data)
print(f"温度: {temp:.1f}°C")
print(f"湿度: {humid:.1f}%")
print(f"时间: {time.ctime(ts)}")
sensor_data = simulate_sensor_data()
print("收到传感器数据,正在解析...")
parse_sensor_data(sensor_data)
常用格式字符速查表
格式字符 | C类型 | Python类型 | 大小(字节) | 说明 |
---|
b | signed char | int | 1 | 有符号字节 |
B | unsigned char | int | 1 |
无符号字节 |
h | short | int | 2 | 短整型 |
H | unsigned short | int | 2 | 无符号短整型 |
i | int | int | 4 | 整型 |
I | unsigned int | int | 4 | 无符号整型 |
f | float | float | 4 | 单精度浮点 |
d | double | float | 8 | 双精度浮点 |
s | char[] | bytes | - | 字符串 |
字节序说明
@
或不写:本机字节序
=
:本机字节序
<
:小端字节序(Intel处理器常用)
>
:大端字节序(网络字节序)
!
:网络字节序(大端)
实用技巧
1. 计算结构体大小
import struct
size = struct.calcsize('ifi')
print(f"数据大小: {size} 字节")
2. 处理可变长度数据
import struct
def pack_string(text):
"""打包字符串:先存长度,再存内容"""
text_bytes = text.encode('utf-8')
length = len(text_bytes)
return struct.pack(f'I{length}s', length, text_bytes)
def unpack_string(data):
"""解包字符串"""
length = struct.unpack('I', data[:4])[0]
text_bytes = struct.unpack(f'{length}s', data[4:4+length])[0]
return text_bytes.decode('utf-8')
original = "Hello Python!"
packed = pack_string(original)
unpacked = unpack_string(packed)
print(f"原文: {original}")
print(f"解包后: {unpacked}")
错误处理
使用struct时要注意数据长度匹配:
import struct
try:
struct.unpack('ii', b'\x01\x02\x03')
except struct.error as e:
print(f"解包错误: {e}")
try:
data = b'\x01\x02\x03\x04\x05\x06\x07\x08'
result = struct.unpack('ii', data)
print(f"解包成功: {result}")
except struct.error as e:
print(f"解包错误: {e}")
struct库看起来复杂,其实就做两件事:
pack:把Python数据变成二进制
unpack:把二进制变成Python数据
掌握了这两个函数,你就能:
解析各种文件格式
处理网络协议数据
与C语言程序交换数据
优化数据存储
学习建议
从简单开始:先练习整数和浮点数的打包解包
理解字节序:网络编程时特别重要
多做实验:用不同的格式字符串试试效果
结合实际:找个具体的文件格式来练手
对Python,AI,自动化办公提效,副业发展等感兴趣的伙伴们,扫码添加逍遥,限免交流群
备注【成长交流】