7.3. struct —将字符串解释为打包的二进制数据

此模块在 Python 值和以 Python 字符串表示的 C 结构之间执行转换。除其他来源外,它可用于处理文件或网络 Connecting 存储的二进制数据。它使用Format Strings作为 C 结构的布局的简明描述以及与 Python 值之间的预期转换。

Note

默认情况下,打包给定 C 结构的结果包括填充字节,以维护所涉及 C 类型的正确对齐;同样,拆箱时也要考虑对齐方式。选择此行为是为了使打包结构的字节与对应的 C 结构的内存中的布局完全对应。要处理与平台无关的数据格式或忽略隐式填充字节,请使用standard大小和对齐方式而不是native大小和对齐方式:有关详细信息,请参见字节 Sequences,大小和对齐方式

7.3.1. Function和异常

该模块定义了以下异常和Function:

  • exception struct. error

    • 在各种情况下都会出现 exception;参数是描述错误的字符串。
  • struct. pack(* fmt v1 v2 ... *)

    • 返回包含根据给定格式打包的值v1, v2, ...的字符串。参数必须与格式所需的值完全匹配。
  • struct. pack_into(* fmt buffer offset v1 v2 ... *)

    • 根据给定格式打包值v1, v2, ...,将打包的字节从* offset 开始写入可写的 buffer *。请注意,偏移量是必填参数。

2.5 版的新Function。

  • struct. unpack(* fmt string *)

    • 根据给定格式解压缩字符串(大概由pack(fmt, ...)打包)。结果是一个 Tuples,即使它只包含一个项目。该字符串必须完全包含该格式所需的数据量(len(string)必须等于calcsize(fmt))。
  • struct. unpack_from(* fmt buffer * [,* offset = 0 *])

    • 根据给定的格式解压缩* buffer *。结果是一个 Tuples,即使它只包含一个项目。 * buffer *必须至少包含格式所需的数据量(len(buffer[offset:])必须至少为calcsize(fmt))。

2.5 版的新Function。

  • struct. calcsize(* fmt *)
    • 返回对应于给定格式的结构的大小(因此返回字符串的大小)。

7.3.2. 格式化字符串

格式字符串是用于在打包和拆包数据时指定预期布局的机制。它们是从Format Characters构建的,它们指定要打包/解包的数据类型。此外,还有用于控制字节 Sequences,大小和对齐方式的特殊字符。

7.3.2.1. 字节 Sequences,大小和对齐方式

默认情况下,C 类型以机器的本机格式和字节 Sequences 表示,并在必要时pass跳过填充字节来正确对齐(根据 C 编译器使用的规则)。

另外,根据下表,格式字符串的第一个字符可用于指示打包数据的字节 Sequences,大小和对齐方式:

CharacterByte orderSizeAlignment
@nativenativenative
=nativestandardnone
<little-endianstandardnone
>big-endianstandardnone
!网络(大端)standardnone

如果第一个字符不是其中一个,则假定为'@'

本地字节 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

7.3.2.2. 格式字符

格式字符具有以下含义;给定它们的类型,C 和 Python 值之间的转换应该显而易见。 “标准大小”列是指使用标准大小时打包值的大小,以字节为单位;也就是说,当格式字符串以'<''>''!''='之一开头时。使用本机大小时,打包值的大小取决于平台。

FormatC TypePython typeStandard sizeNotes
xpad byteno value
cchar长度为 1 的字符串1
bsigned charinteger1(3)
Bunsigned charinteger1(3)
?_Boolbool1(1)
hshortinteger2(3)
Hunsigned shortinteger2(3)
iintinteger4(3)
Iunsigned intinteger4(3)
llonginteger4(3)
Lunsigned longinteger4(3)
qlong longinteger8(2), (3)
Qunsigned long longinteger8(2), (3)
ffloatfloat4(4)
ddoublefloat8(4)
schar[]string
pchar[]string
Pvoid *integer(5), (3)

Notes:

  • '?'转换代码对应于 C99 定义的_Bool类型。如果此类型不可用,则使用char进行模拟。在标准模式下,它始终由一个字节表示。

2.6 版的新Function。

  • 仅当平台 C 编译器支持 C long long或 Windows 上__int64时,'q''Q'转换代码才能在纯模式下使用。它们始终在标准模式下可用。

2.2 版中的新Function。

  • try使用任何整数转换代码打包非整数时,如果非整数具有index()方法,则在打包之前将调用该方法以将参数转换为整数。如果不存在index()方法,或者对index()的调用引发TypeError,则tryint()方法。但是,不建议使用int(),它将提高DeprecationWarning

在 2.7 版中进行了更改:2.7 中新增了对非整数使用index()方法的Function。

在 2.7 版中进行了更改:在 2.7 版之前,并非所有整数转换代码都将使用int()方法进行转换,并且DeprecationWarning仅针对浮点参数引发。

  • 对于'f''d'转换代码,打包表示使用 IEEE 754 二进制 32(对于'f')或二进制 64(对于'd')格式,而与平台使用的浮点格式无关。

  • 'P'格式字符仅可用于本机字节 Sequences(选择为默认字节或与'@'字节 Sequences 字符一起使用)。字节 Sequences 字符'='选择基于主机系统的小端或大端 Sequences。 struct 模块不会将其解释为本地 Sequences,因此'P'格式不可用。

格式字符前面可以有一个整数重复计数。例如,格式字符串'4h'的含义与'hhhh'完全相同。

格式之间的空白字符将被忽略;计数及其格式一定不能包含空格。

对于's'格式字符,该计数被解释为字符串的大小,而不是像其他格式字符一样的重复计数。例如'10s'表示一个 10 字节的字符串,而'10c'表示 10 个字符。如果未提供计数,则默认为 1.对于打包,将适当地将字符串截断或填充空字节以使其适合。对于解压缩,结果字符串始终具有完全指定的字节数。作为一种特殊情况,'0s'表示单个空字符串(而'0c'表示 0 个字符)。

'p'格式字符编码“ Pascal 字符串”,表示存储在固定字节数中的短变长字符串,由计数给定。存储的第一个字节是字符串的长度,即 255,以较小者为准。字符串的字节。如果传递给pack()的字符串太长(大于计数减 1),则仅存储该字符串的前count-1个字节。如果字符串短于count-1,则将其填充为空字节,以便使用所有字节中的精确计数字节。请注意,对于unpack()'p'格式字符占用计数字节,但返回的字符串绝不能包含超过 255 个字符。

对于'P'格式字符,返回值是 Python 整数或长整数,具体取决于将指针强制转换为整数类型时所需的大小。 * NULL *指针将始终作为 Python 整数0返回。打包指针大小的值时,可以使用 Python 整数或长整数对象。例如,Alpha 和 Merced 处理器使用 64 位指针值,这意味着将使用 Python 长整数来保存指针。其他平台使用 32 位指针,并将使用 Python 整数。

对于'?'格式字符,返回值为TrueFalse。打包时,将使用参数对象的真值。本机或标准布尔表示形式中的 0 或 1 将被打包,并且在拆包时任何非零值将为True

7.3.2.3. Examples

Note

所有示例均假定本机字节 Sequences,大小以及与 big-endian 机器的对齐方式。

打包/解包三个整数的基本示例:

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8

可以pass将未打包的字段分配给变量或将结果包装在一个命名的 Tuples 中来命名它们:

>>> record = '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='raymond   ', serialnum=4658, school=264, gradelevel=8)

格式字符的 Sequences 可能会影响大小,因为满足对齐要求所需的填充不同:

>>> pack('ci', '*', 0x12131415)
'*\x00\x00\x00\x12\x13\x14\x15'
>>> pack('ic', 0x12131415, '*')
'\x12\x13\x14\x15*'
>>> calcsize('ci')
8
>>> calcsize('ic')
5

下列格式'llh0l'在末尾指定了两个填充字节,假设长整数在 4 字节边界上对齐:

>>> pack('llh0l', 1, 2, 3)
'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

这仅在原始大小和对齐方式有效时起作用;标准尺寸和对齐方式不会强制执行任何对齐方式。

See also

  • Module array

  • 同类数据的打包二进制存储。

  • Module xdrlib

  • XDR 数据的打包和拆包。

7.3.3. Classes

struct模块还定义了以下类型:

  • 类别 struct. Struct(格式)
    • 返回一个新的 Struct 对象,该对象根据格式字符串* format *写入和读取二进制数据。一次创建一个 Struct 对象并调用其方法比使用相同格式的struct函数更有效,因为格式字符串只需要编译一次。

2.5 版的新Function。

编译的 Struct 对象支持以下方法和属性:

  • pack(* v1 v2 ... *)

    • pack()函数相同,使用已编译的格式。 (len(result)将等于self.size.)
  • pack_into((* buffer offset v1 v2 ... *)

    • pack_into()函数相同,使用已编译的格式。
  • unpack(* string *)

    • unpack()函数相同,使用已编译的格式。 (len(string)必须等于self.size)。
  • unpack_from(* buffer offset = 0 *)

    • unpack_from()函数相同,使用已编译的格式。 (len(buffer[offset:])必须至少为self.size)。
  • format

    • 用于构造此 Struct 对象的格式字符串。
  • size

    • 计算得出的对应于format的结构的大小(以及字符串的大小)。