翻译地址

由于本人能力有限,第一次翻译难免存在模糊,不准确或错误之处,希望见谅和指正。如果能够对你有点帮助,我会感到荣幸。

 

  1. struct—将字节流解释为打包的二进制数据

这个模块执行Python值和C结构之间的转换,C结构表示为Python 字节流对象。它用于处理存储在文件中或来自于网络连接中,以及其他资源的二进制数据。用格式化字符串作为c结构体数据和python转换的值之间的描述。

注意:默认情况下,打包一个C结构体的结果包含填补的字节,这样做是为了适应C语言类型对齐模式。类似的,当解包时也会考虑对齐模式。选择此行为是为了使已打包结构的字节与相应C结构的内存中的布局完全对应。为了处理与平台相关的数据格式或忽略隐式的填补字节,用标准的字节大小和对齐方式代替本机的字节大小和对齐方式。详细请看字节序、字节大小和对齐方式。

struct模块中有的的函数和方法含有buffer参数。这样能够使对象实现缓存协议并提供可读或可读写的缓存区。最常用的字节流和字节数组类型用于这一目的。但是,有很多可以被当成字节流数组的类型能实现缓存协议,这样它们不需要额外复制字节流对象就能读取或填满。

  1. 函数和异常

Struct模块定义如下异常和函数体:

异常struct.error

异常在很多情况下出现。参数是描述哪里出错的字符串。

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

根据格式化字符串format将v1,v2,...进行打包,返回打包的字节流。V1,v2...这些参数必须是按着格式化要求给的值。

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

根据格式化字符串format将v1,v2,...进行打包,并把打包的结果放入可写的缓存区buffer参数中,offset是buffer参数的写入时的偏移量。要注意的是offset是必须给出的参数。

Struct.unpack(format,buffer)

将缓存区buffer里的数据(类似pack(format,...)打包的数据)按照格式化字符串format进行解包。结果是一个列表。即使该列表只有一项。以字节计算的缓存区大小必须匹配格式化参数format要求的大小。

Struct.iter_unpack(format,buffer)

根据格式化字符串format从缓存区buffer中迭代的解包。这个函数会返回一个迭代器。该迭代器将从缓存区buffer中读相同大小的块直到所有的buffer内容用完。缓存区的字节大小必须是format所用的整倍数。Buffer的字节大小通过calcsize()计算得到。

每次迭代都会产生由格式化字符串具体化的元组。

Struct.calcsize(format)

返回结果是结构体的大小,每个与格式化字符串format所占的字节数一致。

  1.  格式化

Format参数是在打包和解包数据的时候,用于具体化想要的布局。他们由format字符组成,这些字符能够在打包和解包时具体化数据的类型。此外,还有特殊的字符用于控制字节序,数据大小和对其方式。

  1. 字节序,数据尺寸和对齐方式

通常情况,C类型能表示本机的数据格式、字节序和合适的对齐方式,如果需要能够通过浏览填充字节做到(根据C编译器使用的规则)。

Format的第一个字符(也可省略)能用来表明打包的数据字节序,尺寸和对齐方式。具体如下表:

字符

字节顺序

尺寸

对齐方式

@

本机

本机

本机

=

本机

标准

<

小端

标准

>

大端

标准

!

网络

标准

 

如果第一个字符不是以上其中一个,就会假定是‘@’字符。

 

本机字节顺序是大端还是小端,依赖于主机系统。例如,intel x86和AMD64(x86-64)是小端模式;Motorola 68000和PowerPC G5是大端模式;ARM和intel itanium具有可切换的字节序(双字节序)。用sys.byteorder来检查你电脑的字节序。

本机的字节大小和对齐方式由C编译器的sizeof表达式决定。这总是跟本地的字节序结合在一起。

标准字节大小和对齐方式只依赖于格式化字符,具体请看格式化字符部分的表格。

请注意‘@’和‘=’字符的不同:两者都是用本地字节序,但数据类型大小和对齐方式是标准的。

字符‘!’适合那些不知道网络字节序是大端模式还是小端模式的人使用。

没有办法表示非本地字节序(可以强制转换);通过在‘<’或‘>’选择合适的一个。

特别提醒:

  1. 填充字节只是自动在连续的结构体成员之间添加。没有填充字节添加在在已编码结构的开始和结尾位置。
  2. 当使用非本机数据类型大小和对齐方式时没有填充字节。例如,有‘<’‘>’‘=’和‘!’
  3. 为了对齐一个具体类型所要求的结构结尾部分,填充重复的0来结束代码的格式化。1.2.2 格式化字符

格式化字符有如下意义;在C和python值之间转换应具体给出它们各自的类型。

标准大小那一列指的是当使用标准大小时打包值的字节大小。意思是说,当format参数以‘<’‘>’‘!’‘=’其中之一时。当使用本地字节大小时,打包值得大小与平台相关。

字符

C类型

Python类型

标准尺寸

(字节数)

备注

x

填充字节

没有值

 

 

c

char

1个字节

1

 

b

Signed char

整型

1

1,3

B

Unsigned char

整型

1

3

?

_Bool

布尔

1

1

h

short

整型

2

3

H

Unsigned short

整型

2

3

i

int

整型

4

3

I

Unsigned int

整型

4

3

l

long

整型

4

3

L

Unsigned long

整型

4

3

q

Long long

整型

8

2,3

Q

Unsigned long long

整型

8

2,3

n

Ssize_t

整型

 

4

N

Size_t

整型

 

4

e

(7)

浮点

2

5

f

float

浮点

4

5

d

double

浮点

8

5

s

Char[]

字节

 

 

p

Char[]

字节

 

 

P

Void*

整型

 

6

 

在版本3.3中的改变:添加’n’和‘N’格式

在版本3.6中的改变:添加‘e’格式

 

注意事项:

  1. ‘?’转换码与C99中规定的布尔类型相对应。如果这个类型不可用,用字符型代替。在标准模式下,char经常表示为一个字节。
  2. ‘q’和‘Q’转换码只有当本机的C编译器支持C的长整型模式下才有效,或者在windows 64位平台。他们在标准模式下经常是有效的。
  3.  当试着用整型转换码打包非整型参数时,如果非整型数据有__index__()方法,在打包之前调用该方法将转换参数。
  4. ‘n’和‘N’转换码只在本地大小(选择默认或‘@’字节序字符)有用。在标准大小模式,能用任何其他整型格式来适应你的应用。
  5.  对于‘f’,‘d’和‘e’转换码,打包的数据分别用IEEE754 32位、64位、16位格式,忽略平台用的浮点格式。
  6. ‘P’格式的字符只用在本地字节序(选择默认或‘@’字节序字符),字节序符号‘=’选择大端模式还是小端模式是由主机系统决定的。Struct不会将它作为本地序,所以‘P’格式无效。
  7. IEEE754 16位的半精度类型在IEEE754的2008版本中介绍。它由1个符号为,5个指数位,11个精度位组成。能够近似表示在6.1e-05到6.5e+04之间的满精度数字。C编译器一般不支持这种类型,能用无符号短整型存储,但不用于数学运算。详细请看维基百科介绍。

 

格式化字符串前能写数字代表字符重复出现的次数。例如,格式化字符串‘4h’和‘hhhh’的效果一样。

 

在格式化字符串之间的空白字符被忽略。一个重复次数和格式化字符之间同样不应包含空白符。

 

对于格式化字符串‘s’,前面的数字代表字节的长度,跟其他格式化字符串前放的数字代表的意义不一样。例如,‘10s’代表10字节的字符串,然而‘10c’代表10个字符,如果没给计数数字,默认为1。在打包时,字符串用空字节来截断或填充以适合打包的格式。在解包时,结果的字节个数就是具体格式化规定的字节数。一个特殊例子,‘0s’代表一个空字符串(‘0c’代表0个字符)

 

当用任何整型格式化字符串打包一个数值x时,如果x的范围在格式化字符串表示的范围外就会报错。

 

上诉情况在版本3.1的改变:而在3.0版本中,整型格式化字符串打包超出范围的数值会报弃用警告。

 

‘p’格式化字符对Pascal字符串编码时,short类型可变长字符串存储在合适的字节数内,字节的个数由count给出。第一个字节存储的字节的长度,或者是255个,或者更小。字符串的字节个数定义如下。如果通过pack()打包的字符串太长(比计的字符串个数减1还长),只存储count-1个字符的字节。如果打包字符串比count-1还少,则用空字节填充使得确实使用了规定的字节数。注意在unpack()是,‘p’格式化字符用count个字节接,但是返回的字符串不能超过255个字节。

 

格式化字符‘?’,返回的值是true或False其中的一个。在打包时参数真正的值被使用。就是说在本地或标准的布尔类型所表示的0或1被打包。在解包时非0值用Ture表示。

 

1.2.3 示例

注意:所有的例子为大端模式电脑的本地字节序,大小和对齐方式。

打包或解包3个整型的基本例子

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

格式化字符‘llh01’要求在末尾添加两个填充字节,假设长整型是以4字节对其的。

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

 

这些只在本地字节和对齐方式起作用。标准大小和对齐方式不会执行任何的对齐方式。