格式字符串
格式字符串是用来在打包和解包数据时指定预期布局的机制。 它们使用指定被打包/解包数据类型的 格式字符 进行构建。 此外,还有一些特殊字符用来控制 字节顺序,大小和对齐方式。
字节顺序,大小和对齐方式
默认情况下,C类型以机器的本机格式和字节顺序表示,并在必要时通过跳过填充字节进行正确对齐(根据C编译器使用的规则)。
或者,根据下表,格式字符串的第一个字符可用于指示打包数据的字节顺序,大小和对齐方式:
字符
字节顺序
大小
对齐方式
@
按原字节
按原字节
按原字节
=
按原字节
标准
无
<
小端
标准
无
>
大端
标准
无
!
网络(=大端)
标准
无
如果第一个字符不是其中之一,则假定为 '@' 。
本机字节顺序可能为大端或是小端,取决于主机系统的不同。 例如, Intel x86 和 AMD64 (x86-64) 是小端的;Motorola 68000 和 PowerPC G5 是大端的;ARM 和 Intel Itanium 具有可切换的字节顺序(双端)。 请使用 sys.byteorder 来检查你的系统字节顺序。
本机大小和对齐方式是使用 C 编译器的 sizeof 表达式来确定的。 这总是会与本机字节顺序相绑定。
标准大小仅取决于格式字符;请参阅 格式字符 部分中的表格。
请注意 '@' 和 '=' 之间的区别:两个都使用本机字节顺序,但后者的大小和对齐方式是标准化的。
格式 '!' 适合给那些宣称他们记不得网络字节顺序是大端还是小端的可怜人使用。
没有什么方式能指定非本机字节顺序(强制字节对调);请正确选择使用 '<' 或 '>'。
注释:
填充只会在连续结构成员之间自动添加。 填充不会添加到已编码结构的开头和末尾。
当使用非本机大小和对齐方式即 '<', '>', '=', and '!' 时不会添加任何填充。
要将结构的末尾对齐到符合特定类型的对齐要求,请以该类型代码加重复计数的零作为格式结束。 参见 例子。
格式字符
格式字符具有以下含义;C 和 Python 值之间的按其指定类型的转换应当是相当明显的。 ‘标准大小’列是指当使用标准大小时以字节表示的已打包值大小;也就是当格式字符串以 '<', '>', '!' 或 '=' 之一开头的情况。 当使用本机大小时,已打包值的大小取决于具体的平台。
格式
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)
在 3.3 版更改: 增加了对 'n' 和 'N' 格式的支持
在 3.6 版更改: 添加了对 'e' 格式的支持。
注释:
'?' 转换码对应于 C99 定义的 _Bool 类型。 如果此类型不可用,则使用 char 来模拟。 在标准模式下,它总是以一个字节表示。
当尝试使用任何整数转换码打包一个非整数时,如果该非整数具有 index() 方法,则会在打包之前调用该方法将参数转换为一个整数。
在 3.2 版更改: 为非整数使用 index() 方法是 3.2 版的新增特性。
'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' 完全相同。
格式之间的空白字符会被忽略;但是计数及其格式字符中不可有空白字符。
对于 's' 格式字符,计数会被解析为字节的长度,而不是像其他格式字符那样的重复计数;例如,'10s' 表示一个 10 字节的字节串,而 '10c' 表示 10 个字符。 如果未给出计数,则默认值为 1。 对于打包操作,字节串会被适当地截断或填充空字节以符合要求。 对于解包操作,结果字节对象总是恰好具有指定数量的字节。 作为特殊情况,'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,则会填充空字节以使得恰好使用了 count 个字节。 请注意对于 unpack(),'p' 格式字符会消耗 count 个字节,但返回的字符串永远不会包含超过 255 个字节。
对于 '?' 格式字符,返回值为 True 或 False。 在打包时将会使用参数对象的逻辑值。 以本机或标准 bool 类型表示的 0 或 1 将被打包,任何非零值在解包时将为 True。
例子
注解 所有示例都假定使用一台大端机器的本机字节顺序、大小和对齐方式。
打包/解包三个整数的基础示例:
>
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
解包的字段可通过将它们赋值给变量或将结果包装为一个具名元组来命名:
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)
格式字符的顺序可能对大小产生影响,因为满足对齐要求所需的填充是不同的:
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' 指定在末尾有两个填充字节,假定 long 类型按 4 个字节的边界对齐:
pack('llh0l', 1, 2, 3) b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'
这仅当本机大小和对齐方式生效时才会起作用;标准大小和对齐方式并不会强制进行任何对齐。
参见
模块 array
被打包为二进制存储的同质数据。
模块 xdrlib
打包和解包 XDR 数据。