首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

struct

该模块执行Python值与C结构之间的转换,表示为Python字符串。这可用于处理存储在文件或网络连接中的二进制数据以及其他来源。它使用格式字符串作为C结构布局的紧凑描述,以及从Python值转换的预期转换。

注意

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

1.功能和例外

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

exception struct.error

在各种场合提出例外; 参数是描述错误的字符串。

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

根据给定的格式返回一个包含值v1,v2,...的字符串。 参数必须完全匹配格式所需的值。

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

v1, v2, ...按照给定的格式打包值,将打包字节写入从偏移量开始的可写缓冲区。请注意,偏移量是必需的参数。

2.5版本中的新功能。

struct.unpack(fmt, string)

根据给定的格式解压字符串(大概是用pack(fmt,...)打包)。 结果是一个元组,即使它只包含一个项目。 该字符串必须包含格式所需的数据量(len(string)必须等于calcsize(fmt))。

struct.unpack_from(fmt, buffer[, offset=0])

按照给定的格式打开缓冲区。 结果是一个元组,即使它只包含一个项目。 缓冲区必须至少包含格式所需的数据量(len(buffer [offset:])必须至少是calcsize(fmt))。

2.5版本中的新功能。

struct.calcsize(fmt)

返回与给定格式相对应的结构体的大小(以及字符串的大小)。

2.格式化字符串

格式字符串是在打包和解包数据时用于指定预期布局的机制。它们由格式字符构成,它指定了打包/解压缩数据的类型。另外,还有用于控制字节顺序,大小和对齐的特殊字符。

2.1 字节顺序,大小和对齐

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

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

字符

字节顺序

大小

对准

@

本地

本地

本地

=

本地

标准

没有

<

小--尾数

标准

没有

大端

标准

没有

!

网络(= big-endian)

标准

没有

如果第一个字符不是其中之一,则假定为“@”。

本地字节顺序是大端或小端,取决于主机系统。例如,Intel x86和AMD64(x86-64)是小端的; 摩托罗拉68000和PowerPC G5是高端的; ARM和Intel Itanium具有可切换的字节序(双字节序)。使用sys.byteorder来检查你的系统的字节序。

原生大小和对齐是使用C编译器的sizeof表达式确定的。这总是与本地字节顺序相结合。

标准尺寸仅取决于格式字符; 请参阅格式字符部分中的表格。

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

表单'!'适用于那些声称自己不记得网络字节顺序是大端还是小端的穷人。

没有办法指示非本地字节顺序(强制字节交换); 使用'<'或'>'的适当选择。

注意:

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

2. 使用非原生大小和对齐时,例如'<','>','='和'!'不会添加填充。

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

2.2 格式化字符

格式字符具有以下含义; 考虑到它们的类型,C和Python值之间的转换应该是显而易见的。 “标准大小”栏是指使用标准大小时打包值的大小(以字节为单位); 也就是说,当格式字符串以'<','>','!'之一开始时 或'='。 使用原生尺寸时,打包值的大小取决于平台。

格式

C 类型

Python 类型

标准大小

注意

x

pad byte

no value

c

char

string of length 1

1

b

signed char

integer

1

(3)

B

unsigned char

integer

1

(3)

?

_Bool

bool

1

(1)

h

short

integer

2

(3)

H

unsigned short

integer

2

(3)

i

int

integer

4

(3)

I

unsigned int

integer

4

(3)

l

long

integer

4

(3)

L

unsigned long

integer

4

(3)

q

long long

integer

8

(2), (3)

Q

unsigned long long

integer

8

(2), (3)

f

float

float

4

(4)

d

double

float

8

(4)

s

char[]

string

p

char[]

string

P

void *

integer

(5), (3)

注意:

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

2.6版本中的新功能。

2. 将'q''Q'只有在平台C编译器支持C转换代码在本地模式中可用long long,或者在Windows上,__int64。它们始终可用于标准模式。

2.2版本中的新功能。

3. 当尝试使用任何整数转换代码打包非整数时,如果非整数具有__index __()方法,则在打包之前调用该方法将参数转换为整数。 如果不存在__index __()方法,或者对__index __()的调用引发TypeError,则尝试__int __()方法。 但是,__int __()的使用已被弃用,并且会引发DeprecationWarning。

在版本2.7中更改:对非整数使用__index __()方法是2.7中的新功能。2.7版中的更改:在版本2.7之前,并非所有整数转换代码都会使用__int __()方法进行转换,并且引发了DeprecationWarning 仅用于float参数。

4. 对于'f''d'转换码,填充表示使用IEEE 754 binary32(对于'f')或binary64(对于'd')格式,而不管由所述平台中使用的浮点格式的。

5. 该'P'格式字符仅适用于本地字节顺序(选择为默认或与'@'字节顺序字符)。字节顺序字符'='选择使用基于主机系统的小端或大端排序。结构模块不会将其解释为本地排序,因此该'P'格式不可用。

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

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

对于's'格式字符,计数被解释为字符串的大小,而不是像其他格式字符一样重复计数; 例如,'10s'表示单个10字节的字符串,而'10c'表示10个字符。 如果没有给出计数,则默认为1.对于打包,字符串将被截断或填充为空字节,以使其合适。 对于解包,结果字符串总是具有指定的字节数。 作为一个特殊情况,'0'表示单个空字符串(而'0c'表示0个字符)。

'p'格式字符编码一个“Pascal字符串”,意思是一个简短的可变长度字符串,存储在固定数量的字节中,由count给出。 存储的第一个字节是字符串的长度,或255,以较小者为准。 字符串的字节在后面。 如果传递给pack()的字符串太长(比计数减1还长),则仅存储字符串的前导count-1字节。 如果字符串比count-1短,则会填充空字节,以便使用全部的精确计数字节。 请注意,对于unpack(),'p'格式字符会消耗计数字节,但返回的字符串不能包含超过255个字符。

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

为了 '?' 格式字符,返回值是True或False。 打包时,使用参数对象的真值。 原生或标准bool表示中的0或1将被打包,并且在解包时任何非零值都将为True。

2.3 例子

注意

所有的例子都假设了一个本地字节顺序,大小,并与一个big-endian机器对齐。

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

代码语言:javascript
复制
>>> 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

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

代码语言:javascript
复制
>>> 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)

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

代码语言:javascript
复制
>>> 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个字节的边界上对齐:

代码语言:javascript
复制
>>> pack('llh0l', 1, 2, 3)
'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

这只适用于本地大小和对齐有效的情况; 标准尺寸和对齐不强制任何对齐。

扩展内容

Module array 打包的二进制存储的同质数据。 Module xdrlib 打包和解压XDR数据。

3.类

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

class struct.Struct(format)

返回一个新的Struct对象,它根据格式字符串格式写入和读取二进制数据。 创建一个Struct对象并调用它的方法比使用相同格式调用结构函数更有效率,因为格式字符串只需编译一次。

2.5版本中的新功能。

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

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

扫码关注腾讯云开发者

领取腾讯云代金券