On this page
struct —将字节解释为打包的二进制数据
源代码: Lib/struct.py
此模块在 Python 值和表示为 Python bytes对象的 C 结构之间执行转换。除其他来源外,它可用于处理文件或网络 Connecting 存储的二进制数据。它使用Format Strings作为 C 结构布局的紧凑描述以及与 Python 值之间的预期转换。
Note
默认情况下,打包给定 C 结构的结果包括填充字节,以维护所涉及 C 类型的正确对齐;同样,拆箱时也要考虑对齐方式。选择此行为是为了使打包结构的字节与对应的 C 结构的内存中的布局完全对应。要处理与平台无关的数据格式或忽略隐式填充字节,请使用standard
大小和对齐方式而不是native
大小和对齐方式:有关详细信息,请参见字节 Sequences,大小和对齐方式。
几个struct函数(以及Struct的方法)带有* buffer *参数。这是指实现Buffer Protocol并提供可读或可写缓冲区的对象。用于此目的的最常见类型是bytes和bytearray,但是可以看作字节数组的许多其他类型实现了缓冲区协议,因此无需从bytes对象进行额外复制就可以读取/填充它们。
函数和异常
该模块定义了以下异常和Function:
exception
struct.
error
- 在各种情况下都会出现 exception;参数是描述错误的字符串。
struct.
pack
(* format , v1 , v2 , ... *)- 返回一个字节对象,其中包含根据格式字符串* format 打包的 v1 , v2 *,...值。参数必须与格式所需的值完全匹配。
struct.
pack_into
(* format , buffer , offset , v1 , v2 , ... *)- 根据格式字符串* format 打包值 v1 , v2 ,…,然后将打包的字节从位置 offset 写入可写缓冲区 buffer 。请注意, offset *是必填参数。
struct.
unpack
(* format , buffer *)- 根据格式字符串* format 从缓冲区 buffer *(大概由
pack(format, ...)
打包)解压缩。结果是一个 Tuples,即使它只包含一个项目。缓冲区大小(以字节为单位)必须与格式要求的大小匹配,如calcsize()所示。
- 根据格式字符串* format 从缓冲区 buffer *(大概由
struct.
unpack_from
(* format , buffer , offset = 0 *)- 根据格式字符串* format 从 buffer 的位置 offset 开始解压缩。结果是一个 Tuples,即使它只包含一个项目。从位置 offset *开始的缓冲区大小(以字节为单位)必须至少为格式要求的大小,如calcsize()所示。
struct.
iter_unpack
(* format , buffer *)- 根据格式字符串* format 从缓冲区 buffer *迭代解压缩。该函数返回一个迭代器,该迭代器将从缓冲区读取大小相等的块,直到其所有内容都被消耗为止。缓冲区大小(以字节为单位)必须是格式要求的大小的倍数,如calcsize()所示。
每次迭代都会产生一个由格式字符串指定的 Tuples。
3.4 版的新Function。
struct.
calcsize
(* format *)- 返回对应于格式字符串* format *的结构的大小(并因此返回
pack(format, ...)
生成的 bytes 对象的大小)。
- 返回对应于格式字符串* format *的结构的大小(并因此返回
Format Strings
格式字符串是用于在打包和拆包数据时指定预期布局的机制。它们是从Format Characters构建的,它们指定要打包/解包的数据类型。此外,还有用于控制字节 Sequences,大小和对齐方式的特殊字符。
字节 Sequences,大小和对齐方式
默认情况下,C 类型以机器的本机格式和字节 Sequences 表示,并在必要时pass跳过填充字节来正确对齐(根据 C 编译器使用的规则)。
另外,根据下表,格式字符串的第一个字符可用于指示打包数据的字节 Sequences,大小和对齐方式:
Character | Byte order | Size | Alignment |
---|---|---|---|
@ |
native | native | native |
= |
native | standard | none |
< |
little-endian | standard | none |
> |
big-endian | standard | none |
! |
网络(大端) | standard | none |
如果第一个字符不是其中一个,则假定为'@'
。
本地字节 Sequences 为大端或小端,具体取决于主机系统。例如,Intel x86 和 AMD64(x86-64)是低位字节序;摩托罗拉 68000 和 PowerPC G5 是大端的; ARM 和 Intel Itanium 具有可切换的字节序(bi-endian)。使用sys.byteorder
检查系统的字节 Sequences。
原始大小和对齐方式是使用 C 编译器的sizeof
表达式确定的。这始终与本机字节 Sequences 结合在一起。
标准尺寸仅取决于格式字符;请参阅“ Format Characters”部分中的表格。
注意'@'
和'='
之间的区别:两者都使用本机字节 Sequences,但是后者的大小和对齐方式是标准化的。
'!'
形式可用于那些声称自己不记得网络字节 Sequences 是大端还是小端的可怜人。
无法指示非本机字节 Sequences(强制字节交换)。使用'<'
或'>'
的适当选择。
Notes:
仅在连续的结构成员之间自动添加填充。在编码结构的开头或结尾不添加填充。
使用非原生大小和对齐方式时,例如,不添加填充。与“ <', '>”,“ =”和“!”。
要将结构的末尾与特定类型的对齐要求对齐,请使用该类型的代码结束该格式,并重复计数为零。参见Examples。
Format Characters
格式字符具有以下含义;给定它们的类型,C 和 Python 值之间的转换应该显而易见。 “标准大小”列是指使用标准大小时打包值的大小,以字节为单位;也就是说,当格式字符串以'<'
,'>'
,'!'
或'='
之一开头时。使用本机大小时,打包值的大小取决于平台。
Format | C Type | Python type | Standard size | Notes |
---|---|---|---|---|
x |
pad byte | no value | ||
c |
char |
长度为 1 的字节 | 1 | |
b |
signed char |
integer | 1 | (1), (2) |
B |
unsigned char |
integer | 1 | (2) |
? |
_Bool |
bool | 1 | (1) |
h |
short |
integer | 2 | (2) |
H |
unsigned short |
integer | 2 | (2) |
i |
int |
integer | 4 | (2) |
I |
unsigned int |
integer | 4 | (2) |
l |
long |
integer | 4 | (2) |
L |
unsigned long |
integer | 4 | (2) |
q |
long long |
integer | 8 | (2) |
Q |
unsigned long long |
integer | 8 | (2) |
n |
ssize_t |
integer | (3) | |
N |
size_t |
integer | (3) | |
e |
(6) | float | 2 | (4) |
f |
float |
float | 4 | (4) |
d |
double |
float | 8 | (4) |
s |
char[] |
bytes | ||
p |
char[] |
bytes | ||
P |
void * |
integer | (5) |
在版本 3.3 中进行了更改:添加了对'n'
和'N'
格式的支持。
在版本 3.6 中进行了更改:添加了对'e'
格式的支持。
Notes:
'?'
转换代码对应于 C99 定义的_Bool
类型。如果此类型不可用,则使用char
进行模拟。在标准模式下,它始终由一个字节表示。
- try使用任何整数转换代码打包非整数时,如果非整数具有index()方法,则在打包之前将调用该方法以将参数转换为整数。
在版本 3.2 中进行了更改:非整数使用index()方法是 3.2 中的新增Function。
'n'
和'N'
转换代码仅适用于本机大小(选择为默认大小或'@'
字节 Sequences 字符)。对于标准大小,您可以使用适合您的应用程序的任何其他整数格式。对于
'f'
,'d'
和'e'
转换代码,打包表示使用 IEEE 754 binary32,binary64 或 binary16 格式(分别用于'f'
,'d'
或'e'
),而与平台使用的浮点格式无关。'P'
格式字符仅可用于本机字节 Sequences(选择为默认字节或与'@'
字节 Sequences 字符一起使用)。字节 Sequences 字符'='
选择基于主机系统的小端或大端 Sequences。 struct 模块不会将其解释为本地 Sequences,因此'P'
格式不可用。在IEEE 754 标准的 2008 年修订版中引入了 IEEE 754 binary16“半精度”类型。它具有符号位,5 位指数和 11 位精度(明确存储了 10 位),并且可以全精度表示大约
6.1e-05
和6.5e+04
之间的数字。这种类型不受 C 编译器的广泛支持:在典型的计算机上,无符号的 short 可以用于存储,但不能用于 math 运算。有关更多信息,请参见半精度浮点格式上的 Wikipedia 页面。
格式字符前面可以有一个整数重复计数。例如,格式字符串'4h'
的含义与'hhhh'
完全相同。
格式之间的空白字符将被忽略;计数及其格式一定不能包含空格。
对于's'
格式字符,该计数被解释为字节的长度,而不是其他格式字符的重复计数;例如'10s'
表示一个 10 字节的字符串,而'10c'
表示 10 个字符。如果未提供计数,则默认为 1.对于打包,将适当地将字符串截断或填充空字节以使其适合。对于解压缩,生成的 bytes 对象始终具有完全指定的字节数。作为一种特殊情况,'0s'
表示单个空字符串(而'0c'
表示 0 个字符)。
使用整数格式('b'
,'B'
,'h'
,'H'
,'i'
,'I'
,'l'
,'L'
,'q'
,'Q'
)之一打包值x
时,如果x
超出该格式的有效范围,则引发struct.error。
在版本 3.1 中进行了更改:在 3.0 中,某些整数格式包装了超出范围的值并提高了DeprecationWarning而不是struct.error。
'p'
格式字符编码“ Pascal 字符串”,表示存储在固定字节数中的短变长字符串,由计数给定。存储的第一个字节是字符串的长度,即 255,以较小者为准。字符串的字节。如果传递给pack()的字符串太长(大于计数减 1),则仅存储该字符串的前count-1
个字节。如果字符串短于count-1
,则将其填充为空字节,以便使用所有字节中的精确计数字节。请注意,对于unpack(),'p'
格式字符占用count
个字节,但返回的字符串绝不能包含超过 255 个字节。
对于'?'
格式字符,返回值为True或False。打包时,将使用参数对象的真值。本机或标准布尔表示形式中的 0 或 1 将被打包,并且在拆包时任何非零值将为True
。
Examples
Note
所有示例均假定本机字节 Sequences,大小以及与 big-endian 机器的对齐方式。
打包/解包三个整数的基本示例:
>>> from struct import *
>>> pack('hhl', 1, 2, 3)
b'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8
可以pass将未打包的字段分配给变量或将结果包装在一个命名的 Tuples 中来命名它们:
>>> record = b'raymond \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)
>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond ', serialnum=4658, school=264, gradelevel=8)
格式字符的 Sequences 可能会影响大小,因为满足对齐要求所需的填充不同:
>>> pack('ci', b'*', 0x12131415)
b'*\x00\x00\x00\x12\x13\x14\x15'
>>> pack('ic', 0x12131415, b'*')
b'\x12\x13\x14\x15*'
>>> calcsize('ci')
8
>>> calcsize('ic')
5
下列格式'llh0l'
在末尾指定了两个填充字节,假设长整数在 4 字节边界上对齐:
>>> pack('llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'
这仅在原始大小和对齐方式有效时起作用;标准尺寸和对齐方式不会强制执行任何对齐方式。
Classes
struct模块还定义了以下类型:
- 类别
struct.
Struct
(格式)- 返回一个新的 Struct 对象,该对象根据格式字符串* format *写入和读取二进制数据。一次创建一个 Struct 对象并调用其方法比使用相同格式的struct函数更有效,因为格式字符串只需要编译一次。
编译的 Struct 对象支持以下方法和属性:
pack
(* v1 , v2 , ... *)pack_into
((* buffer , offset , v1 , v2 , ... *)- 与pack_into()函数相同,使用已编译的格式。
unpack
(* buffer *)unpack_from
(* buffer , offset = 0 *)- 与unpack_from()函数相同,使用已编译的格式。从* offset *位置开始的缓冲区大小(以字节为单位)必须至少为size。
iter_unpack
(* buffer *)- 与iter_unpack()函数相同,使用已编译的格式。缓冲区的大小(以字节为单位)必须是size的倍数。
3.4 版的新Function。
format
- 用于构造此 Struct 对象的格式字符串。