struct ---将字节解释为压缩二进制数据

源代码: Lib/struct.py


此模块在python值和c结构(表示为python)之间执行转换。 bytes 物体。这可以用于处理存储在文件中或来自网络连接以及其他来源的二进制数据。它使用 格式字符串 作为对C结构布局和对python值的预期转换的简洁描述。

注解

默认情况下,打包给定的C结构的结果包括pad字节,以便为所涉及的C类型保持适当的对齐;同样,在解包时也考虑了对齐。选择此行为是为了使打包结构的字节与相应C结构的内存中的布局完全对应。要处理与平台无关的数据格式或忽略隐式PAD字节,请使用 standard 大小和对齐方式,而不是 native 尺寸和对齐方式:请参见 字节顺序、大小和对齐方式 有关详细信息。

几个 struct 功能(和方法 Struct 拿一个 缓冲区 参数。这指的是实现 缓冲协议 并提供可读或可读写缓冲区。最常用的类型是 bytesbytearray ,但是许多其他可以被视为字节数组的类型实现了缓冲区协议,这样就可以在不从 bytes 对象。

功能和例外

模块定义以下异常和函数:

exception struct.error

在各种情况下引发的异常;参数是描述错误的字符串。

struct.pack(format, v1, v2, ...)

返回包含值的bytes对象 v1v2 ,…按格式字符串封装 格式 . 参数必须与格式要求的值完全匹配。

struct.pack_into(format, buffer, offset, v1, v2, ...)

封装价值 v1v2 ,…根据格式字符串 格式 并将压缩字节写入可写缓冲区 缓冲区 从位置开始 抵消 .注意 抵消 是必需的参数。

struct.unpack(format, buffer)

从缓冲区解包 缓冲区 (大概由 pack(format, ...) )根据格式字符串 格式 . 结果是一个元组,即使它只包含一个项。缓冲区的字节大小必须与格式所需的大小匹配,如 calcsize() .

struct.unpack_from(format, /, buffer, offset=0)

解包 缓冲区 从位置开始 抵消 ,根据格式字符串 格式 . 结果是一个元组,即使它只包含一个项。缓冲区的大小(以字节为单位),从位置开始 抵消 ,必须至少为格式所需的大小,如 calcsize() .

struct.iter_unpack(format, buffer)

从缓冲区迭代解包 缓冲区 根据格式字符串 格式 . 此函数返回一个迭代器,该迭代器将从缓冲区中读取大小相等的块,直到所有内容都被消耗掉。缓冲区的字节大小必须是格式所需大小的倍数,如 calcsize() .

每个迭代生成一个由格式字符串指定的元组。

3.4 新版功能.

struct.calcsize(format)

返回结构的大小(以及由此产生的bytes对象的大小) pack(format, ...) )对应格式字符串 格式 .

格式字符串

格式字符串是用于在打包和解包数据时指定预期布局的机制。它们是由 设置字符格式 ,指定要打包/解包的数据类型。此外,还有一些特殊的字符用于控制 字节顺序、大小和对齐方式 .

字节顺序、大小和对齐方式

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

或者,格式字符串的第一个字符可用于根据下表指示压缩数据的字节顺序、大小和对齐方式:

性格

字节顺序

尺寸

对准

@

本地的

本地的

本地的

=

本地的

标准

没有人

<

小字节

标准

没有人

>

大字节

标准

没有人

!

网络(=big endian)

标准

没有人

如果第一个字符不是其中之一, '@' 假设。

本机字节顺序是big-endian或little-endian,具体取决于主机系统。例如,Intel x86和AMD64(x86-64)是小endian;Motorola 68000和PowerPC G5是big endian;ARM和Intel Itanium具有可切换的endianness(bi endian)。使用 sys.byteorder 检查系统的结尾。

使用C编译器确定本机大小和对齐方式 sizeof 表达式。这总是与本机字节顺序结合在一起。

标准大小仅取决于格式字符;请参阅中的表 设置字符格式 部分。

注意两者之间的区别 '@''=' :两者都使用本机字节顺序,但后者的大小和对齐方式是标准化的。

形式 '!' 表示网络字节顺序,它始终是中定义的big-endian IETF RFC 1700 .

无法指示非本机字节顺序(强制字节交换);请使用 '<''>' .

笔记:

  1. 填充仅自动添加到连续的结构成员之间。在编码结构的开头或结尾不添加填充。

  2. 使用非本机大小和对齐方式时不添加填充,例如,使用“<”、“>”、“=”和“!”.

  3. 要使结构的结尾与特定类型的对齐要求对齐,请使用该类型的代码结束格式,重复计数为零。见 实例 .

设置字符格式

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

格式

C型

Python 型

标准尺寸

笔记

x

填充字节

无价值

c

char

长度为1的字节

1

b

signed char

整数

1

(1) ,(二)

B

unsigned char

整数

1

(2)

?

_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)

在 3.3 版更改: 增加了对 'n''N' 格式。

在 3.6 版更改: 增加了对 'e' 格式。

笔记:

  1. 这个 '?' 转换代码对应于 _Bool 由C99定义的类型。如果此类型不可用,则使用 char . 在标准模式下,它总是用一个字节表示。

  2. 如果非整数具有 __index__() 方法,然后调用该方法在打包之前将参数转换为整数。

    在 3.2 版更改: 增加了 __index__() 非整数的方法。

  3. 这个 'n''N' 转换代码仅适用于本机大小(选择为默认值或 '@' 字节顺序字符)。对于标准大小,您可以使用其他适合您的应用程序的整数格式。

  4. 对于 'f''d''e' 转换代码,打包表示使用IEEE754Binary32、Binary64或Binary16格式(用于 'f''d''e' 分别),不考虑平台使用的浮点格式。

  5. 这个 'P' 格式字符仅可用于本机字节排序(选择作为默认值或使用 '@' 字节顺序字符)。字节顺序字符 '=' 根据主机系统选择使用小尾数或大尾数排序。结构模块不将其解释为本机排序,因此 'P' 格式不可用。

  6. IEEE754二进制16“半精度”类型在2008年修订版的 IEEE 754 standard . 它有一个符号位、一个5位指数和11位精度(显式存储了10位),可以表示大约介于 6.1e-056.5e+04 完全精确。C编译器并不广泛支持这种类型:在典型的计算机上,无符号短代码可以用于存储,但不能用于数学运算。参见维基百科网页 half-precision floating-point format 更多信息。

格式字符前面可以是整数重复计数。例如,格式字符串 '4h' 意思与 'hhhh' .

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

对于 's' 格式字符,计数被解释为字节的长度,而不是像其他格式字符一样的重复计数;例如, '10s' 表示单个10字节字符串,而 '10c' 表示10个字符。如果未给定计数,则默认为1。对于打包,字符串被截断或用空字节填充,以使其适合。对于解包,生成的bytes对象始终具有指定的字节数。作为一种特殊情况, '0s' 表示单个空字符串(while '0c' 表示0个字符)。

打包值时 x 使用整数格式之一 ('b''B''h''H''i''I''l''L''q''Q' )如果 x 超出该格式的有效范围,则 struct.error 提高了。

在 3.1 版更改: 以前,一些整数格式包装超出范围的值并引发 DeprecationWarning 而不是 struct.error .

这个 'p' 格式字符编码“pascal字符串”,表示存储在 固定字节数 ,由计数给出。存储的第一个字节是字符串的长度,或255,以较小的为准。后面是字符串的字节。如果字符串传入 pack() 太长(比计数减去1长),只有前导 count-1 存储字符串的字节。如果字符串短于 count-1 ,它用空字节填充,以便使用所有字节中的精确计数。请注意 unpack() , the 'p' 格式化字符消耗 count 字节,但返回的字符串不能包含超过255个字节。

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

实例

注解

所有示例都假定本机字节顺序、大小和与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

可以通过将解包字段分配给变量或将结果封装到命名的元组来命名解包字段:

>>> 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' 在末尾指定两个pad字节,假定long在4字节边界上对齐:

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

这仅在本机大小和对齐有效时有效;标准大小和对齐不强制任何对齐。

参见

模块 array

齐次数据的压缩二进制存储。

模块 xdrlib

xdr数据的打包和解包。

Classes

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

class struct.Struct(format)

返回一个新的结构对象,该对象根据格式字符串写入和读取二进制数据 格式 . 一次创建结构对象并调用其方法比调用 struct 具有相同格式的函数,因为格式字符串只需要编译一次。

注解

传递给的最新格式字符串的编译版本 Struct 模块级函数被缓存,因此只使用少数格式字符串的程序不需要担心重用单个字符串 Struct 实例。

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

pack(v1, v2, ...)

pack() 函数,使用已编译的格式。 (len(result) 意志平等 size

pack_into(buffer, offset, v1, v2, ...)

pack_into() 函数,使用已编译的格式。

unpack(buffer)

unpack() 函数,使用已编译的格式。缓冲区的字节大小必须等于 size .

unpack_from(buffer, offset=0)

unpack_from() 函数,使用已编译的格式。缓冲区的大小(以字节为单位),从位置开始 抵消 ,必须至少为 size .

iter_unpack(buffer)

iter_unpack() 函数,使用已编译的格式。缓冲区的字节大小必须是 size .

3.4 新版功能.

format

用于构造此结构对象的格式字符串。

在 3.7 版更改: 格式字符串类型现在为 str 而不是 bytes .

size

结构(以及由此产生的bytes对象)的计算大小 pack() 方法)对应于 format .