1. struct介绍
此模块可以执行Python值和以Python bytes对象表示的C结构之间的转换。这可以被用来处理存储在文件中或是从网络连接等其他来源获取的二进制数据。它使用格式字符串表示C结构来与Python值进行双向转换。
注释:默认情况下,打包给定的C结构(比如:int short long char 等)的结果会包含填充字节以使得所涉及的C结构类型能保持正确的对齐;类似地,对齐在解包时也会应该被纳入考虑。
>>> struct.pack('i', 0x0f)
b'\x0f\x00\x00\x00' // 后边的\x00\x00\x00就是填充字节,因为'i'表示的是C语言中的int类型,在C中int类型占用4个字节。
// 如果指定C类型为i也就是int,那么被解包的二进制数据也应该符合C类型的长度。
>>> struct.unpack('i', b'\x0f') // 'i' 长度为4, b'\x0f'长度为1, 所以会报以下错误。
Traceback (most recent call last):
File "<input>", line 1, in <module>
struct.error: unpack requires a buffer of 4 bytes
>>> struct.unpack('i', b'\x0f\x00\x00\x00') // 'i' size is 4, b'\x0f\x00\x00\x00'size is 4, 所以不会报错.
(15,)
>>> struct.unpack('b', b'\x0f') // 'b' 为 signed cahr 长度为1, b'\x0f' 长度也为1.
(15,)
- 注: 两个十六进制数为什么精确对应二进制一个字节?
2. 格式字符串
格式字符串是用来在打包和解包数据时指定预期布局的机制(字节顺序、大小、对齐方式)。他们使用指定被打包/解包数据类型的格式字符进行构建。此外,还有一些特殊字符用来控制字节顺序,大小和对齐方式。
1) 字节顺序、大小和对齐方式
字符 | 字节顺序 | 大小 | 对齐方式 |
---|---|---|---|
@ | 按原字节 | 按原字节 | 按原字节 |
= | 按原字节 | 标准 | 无 |
< | 小端 | 标准 | 无 |
> | 大端 | 标准 | 无 |
! | 网络(=大端) | 标准 | 无 |
注: 如果pack(format, v1)或者unpack(format, v1)中format中没有上述任何一个符号,则默认为@
2)格式字符
| 格式 | 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) | 浮点数 | 2 | (4) | | f | float | 浮点数 | 4 | (4) | | d | double | 浮点数 | 8 | (4) | | s | char[] | 字节串 | | | | p | char[] | 字节串 | | | | P | void * | 整数 | | (5) |
注释
- ‘?’ 转换码对应于C99定义的_Bool类型。如果此类型不可用, 则使用char来模拟。在标准模式下,它总是以一个字节表示。
- 当尝试使用任何整数转换码打包一个非整数时,如果该非整数具有index()方法,则会在打包之前调用该方法将参数转换为一个整数。
- ‘n’ 和 ‘N’ 转换码仅对本机大小可用(选择为默认或使用’@’字节顺序字符)。对于标准大小,你可以使用使用你的应用的任何其他整数格式。
- 对于
'f'
,'d'
和'e'
转换码,打包表示形式将使用 IEEE 754 binary32, binary64 或 binary16 格式 (分别对应于'f'
,'d'
或'e'
),无论平台使用何种浮点格式。 'P'
格式字符仅对本机字节顺序可用(选择为默认或使用'@'
字节顺序字符)。 字节顺序字符'='
选择使用基于主机系统的小端或大端排序。 struct 模块不会将其解读为本机排序,因此'P'
格式将不可用。- IEEE 754 binary16 “半精度” 类型是在 IEEE 754 标准 的 2008 修订版中引入的。 它包含一个符号位,5 个指数位和 11 个精度位(明确存储 10 位),可以完全精确地表示大致范围在
6.1e-05
和6.5e+04
之间的数字。 此类型并不被 C 编译器广泛支持:在一台典型的机器上,可以使用 unsigned short 进行存储,但不会被用于数学运算。 请参阅维基百科页面 half-precision floating-point format 了解详情。
格式字符之前可以带有整数重复计数。 例如,格式字符串 '4h'
的含义与 'hhhh'
完全相同。
// '2i' 等价于 'ii'
>>> struct.pack('2i', 0x50, 0x15)
b'P\x00\x00\x00\x15\x00\x00\x00'
>>> struct.pack('ii', 0x50, 0x15)
b'P\x00\x00\x00\x15\x00\x00\x00'
格式之间的空白字符会被忽略;但是计数及其格式字符中不可有空白字符。
>>> struct.pack('! 2b', 0x50, 0x05)
b'P\x05'
>>> struct.pack('!2 b', 0x50, 0x05)
Traceback (most recent call last):
File "<input>", line 1, in <module>
struct.error: bad char in struct format