python中struct 模块用于python数据结构与C结构之间的相互转换,其中C结构是用一种格式化字符串表示的,学习struct 模块的难点就在这个格式化字符串上,强烈建议最好了解下C语言结构体的相关知识点,如果比较熟悉C语言结构体及对齐,学习struct 模块轻而易举。
官方英文文档:struct — Interpret strings as packed binary data¶
struct 模块方法
#将v1 v2按照fmt 转化为一个字节流(bytes)
struct.pack(fmt, v1, v2, ...)
#将v1 v2按照fmt 转化为一个字节流(bytes),并写入buffer,从位置offset处开始写入
struct.pack_into(fmt, buffer, offset, v1, v2, ...)
#将字节流按照fmt转化为python对象返回
struct.unpack(fmt, string)
#同unpack,只是针特定buffer转化为python对象返回
struct.unpack_from(fmt, buffer[, offset=0])
#返回fmt的所表示的C结构体所占字节大小
struct.calcsize(fmt)
#如果一述函数使用过程中fmt格式不对,会抛出这个异常
exception struct.error
格式化串
格式化串的字符根据功能不同可以分为两类,一类用于控制字节顺序、大小及对齐(Byte Order, Size, and Alignment),另一类用于表示结构体的组成(Format Characters)。
Byte Order, Size, and Alignment
字节顺序对齐相关知识详见C语言字节对齐问题详解(对齐、字节序、网络序等)
字符 | 字节序 | 大小 | 对齐方式 |
---|---|---|---|
@ | 原生 | 原生 | 原生 |
= | 原生 | 标准 | 无 |
< | 小端 | 标准 | 无 |
> | 大端 | 标准 | 无 |
! | 网络字节序 | 标准 | 无 |
注:原生指使用本地机器的字节序、大小和对齐方式
这些字符出现在格式化字符串的开头,如果没有给出,默认为@,字节大小一列中的标准是指下面的Format Characters。
Format Characters
字符 | C Type | Python type | Standard size |
---|---|---|---|
x | pad byte | no value | |
c | char | string of length 1 | 1 |
b | signed char | integer | 1 |
B | unsigned char | integer | 1 |
? | _Bool | bool | 1 |
h | short | integer | 2 |
H | unsigned short | integer | 2 |
i | int | integer | 4 |
I | unsigned int | integer | 4 |
l | long | integer | 4 |
L | unsigned long | integer | 4 |
q | long long | integer | 8 |
Q | unsigned long long | integer | 8 |
f | float | float | 4 |
d | double | float | 8 |
s | char[] | string | |
p | char[] | string | |
P | void * | integer |
一个栗子
下面通过一个简单的例子说明 struct模块的使用
import struct
str = struct.pack('=H4sII', 0x04, b'aaaa', 0x01, 0x0e)
a, b, c, d = struct.unpack('=H4sll', str)
print("a={0},b={1},c={2},d={3}.".format(a, b, c, d))
print(struct.calcsize('=H4sII'))
运行结果
a=4,b=b'aaaa',c=1,d=14.
14
格式化字串’=H4sII’所表示的C结构体写成C语言如下:
struct H4sII
{
unsigned short a;
char b[4];
unsigned int c;
unsigned int d;
}
=表示使用本机字节序、标准大小、无对齐
H表示unsigned short 占2个字节大小
4s 一个长度为4的字符数组占4个字节大小
I表示unsigned int 占4个字大小
由于没有对齐,故格式化字串’=H4sII’表示的结构体大小为2+4+4+4=14
如果去掉=号,会怎么样呢?
import struct
str = struct.pack('H4sII', 0x04, b'aaaa', 0x01, 0x0e)
a, b, c, d = struct.unpack('H4sll', str)
print("a={0},b={1},c={2},d={3}.".format(a, b, c, d))
print(struct.calcsize('H4sII'))
运行结果
a=4,b=b'aaaa',c=1,d=14.
16
如果pack与unpack的时候使用的格式化串不一致,会抛出异常 struct.error
import struct
str = struct.pack('=H4sII', 0x04, b'aaaa', 0x01, 0x0e)
a, b, c, d = struct.unpack('H4sll', str)
print("a={0},b={1},c={2},d={3}.".format(a, b, c, d))
运行结果
Traceback (most recent call last):
File "D:/home/test1.py", line 4, in <module>
a, b, c, d = struct.unpack('H4sll', str)
struct.error: unpack requires a bytes object of length 16