用 struct
模块可以实现字符串和二进制数据间的相互转换,常用来解析网络数据、C 语言结构体对应的数据。
常用方法
struct.pack(fmt, data1, data2, ...)
:用于将 Python 的值根据格式字符串转换为 bytes
struct.unpack(fmt, bytes)
:将 bytes 按照格式字符串给定的格式解析成一个元组。
格式字符串
字节顺序,大小和对齐方式:
字符 | 字节顺序 | 大小 | 对齐方式 |
---|---|---|---|
@ |
按原字节 | 按原字节 | 按原字节 |
= |
按原字节 | 标准 | 无 |
< |
小端 | 标准 | 无 |
> |
大端 | 标准 | 无 |
! |
网络(=大端) | 标准 | 无 |
格式字符:
格式 | C 类型 | Python 类型 | 标准大小 | 注释 |
---|---|---|---|---|
x |
填充字节 | 无 | ||
c |
char |
长度为 1 的字节串 | 1 | |
b |
signed char |
整数 | 1 | (1), (2) |
B |
unsigned char |
整数 | 1 | (2) |
? |
_Bool |
bool | 1 | (1) |
h |
short |
整数 | 2 | (2) |
H |
unsigned short |
整数 | 2 | (2) |
i |
int |
整数 | 4 | (2) |
I |
unsigned int |
整数 | 4 | (2) |
l |
long |
整数 | 4 | (2) |
L |
unsigned long |
整数 | 4 | (2) |
q |
long long |
整数 | 8 | (2) |
Q |
unsigned long long |
整数 | 8 | (2) |
n |
ssize_t |
整数 | (3) | |
N |
size_t |
整数 | (3) | |
e |
(6) | float | 2 | (4) |
f |
float |
float | 4 | (4) |
d |
double |
float | 8 | (4) |
s |
char[] |
字节串 | ||
p |
char[] |
字节串 | ||
P |
void * |
整数 | (5) |
使用样例
样例一:将 int
转换为 bytes
,然后再转换成两个 short
import struct
bin_num = struct.pack('>i', 65536) # 使用大端模式读入
print(bin_num) # b'\x00\x00\x01\x00'
print(struct.unpack('>hh', bin_num)) # (1, 0)
样例二:元组和 C 结构体相互转换
'''
假设结构体的结构如下:
struct header {
int buf1;
double buf2;
char buf3[11];
}
'''
import struct
buf1 = xxx
buf2 = xxx.xxx
buf3 = "xxxxxxxxxxx"
header = struct.pack('id11s', buf1, buf2, bytes(buf3, encoding='ascii')) # 构造结构体
buf1, buf2, buf3 = struct.unpack('id11s', header) # 解包结构体
样例三:实现 OTP 算法(见此文:OTP 介绍与实现)