由于本人能力有限,第一次翻译难免存在模糊,不准确或错误之处,希望见谅和指正。如果能够对你有点帮助,我会感到荣幸。
- struct—将字节流解释为打包的二进制数据
这个模块执行Python值和C结构之间的转换,C结构表示为Python 字节流对象。它用于处理存储在文件中或来自于网络连接中,以及其他资源的二进制数据。用格式化字符串作为c结构体数据和python转换的值之间的描述。
注意:默认情况下,打包一个C结构体的结果包含填补的字节,这样做是为了适应C语言类型对齐模式。类似的,当解包时也会考虑对齐模式。选择此行为是为了使已打包结构的字节与相应C结构的内存中的布局完全对应。为了处理与平台相关的数据格式或忽略隐式的填补字节,用标准的字节大小和对齐方式代替本机的字节大小和对齐方式。详细请看字节序、字节大小和对齐方式。
struct模块中有的的函数和方法含有buffer参数。这样能够使对象实现缓存协议并提供可读或可读写的缓存区。最常用的字节流和字节数组类型用于这一目的。但是,有很多可以被当成字节流数组的类型能实现缓存协议,这样它们不需要额外复制字节流对象就能读取或填满。
- 函数和异常
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所占的字节数一致。
- 格式化
Format参数是在打包和解包数据的时候,用于具体化想要的布局。他们由format字符组成,这些字符能够在打包和解包时具体化数据的类型。此外,还有特殊的字符用于控制字节序,数据大小和对其方式。
- 字节序,数据尺寸和对齐方式
通常情况,C类型能表示本机的数据格式、字节序和合适的对齐方式,如果需要能够通过浏览填充字节做到(根据C编译器使用的规则)。
Format的第一个字符(也可省略)能用来表明打包的数据字节序,尺寸和对齐方式。具体如下表:
字符 | 字节顺序 | 尺寸 | 对齐方式 |
@ | 本机 | 本机 | 本机 |
= | 本机 | 标准 | 无 |
< | 小端 | 标准 | 无 |
> | 大端 | 标准 | 无 |
! | 网络 | 标准 | 无 |
如果第一个字符不是以上其中一个,就会假定是‘@’字符。
本机字节顺序是大端还是小端,依赖于主机系统。例如,intel x86和AMD64(x86-64)是小端模式;Motorola 68000和PowerPC G5是大端模式;ARM和intel itanium具有可切换的字节序(双字节序)。用sys.byteorder来检查你电脑的字节序。
本机的字节大小和对齐方式由C编译器的sizeof表达式决定。这总是跟本地的字节序结合在一起。
标准字节大小和对齐方式只依赖于格式化字符,具体请看格式化字符部分的表格。
请注意‘@’和‘=’字符的不同:两者都是用本地字节序,但数据类型大小和对齐方式是标准的。
字符‘!’适合那些不知道网络字节序是大端模式还是小端模式的人使用。
没有办法表示非本地字节序(可以强制转换);通过在‘<’或‘>’选择合适的一个。
特别提醒:
- 填充字节只是自动在连续的结构体成员之间添加。没有填充字节添加在在已编码结构的开始和结尾位置。
- 当使用非本机数据类型大小和对齐方式时没有填充字节。例如,有‘<’‘>’‘=’和‘!’
- 为了对齐一个具体类型所要求的结构结尾部分,填充重复的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’格式
注意事项:
- ‘?’转换码与C99中规定的布尔类型相对应。如果这个类型不可用,用字符型代替。在标准模式下,char经常表示为一个字节。
- ‘q’和‘Q’转换码只有当本机的C编译器支持C的长整型模式下才有效,或者在windows 64位平台。他们在标准模式下经常是有效的。
- 当试着用整型转换码打包非整型参数时,如果非整型数据有__index__()方法,在打包之前调用该方法将转换参数。
- ‘n’和‘N’转换码只在本地大小(选择默认或‘@’字节序字符)有用。在标准大小模式,能用任何其他整型格式来适应你的应用。
- 对于‘f’,‘d’和‘e’转换码,打包的数据分别用IEEE754 32位、64位、16位格式,忽略平台用的浮点格式。
- ‘P’格式的字符只用在本地字节序(选择默认或‘@’字节序字符),字节序符号‘=’选择大端模式还是小端模式是由主机系统决定的。Struct不会将它作为本地序,所以‘P’格式无效。
- 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'
这些只在本地字节和对齐方式起作用。标准大小和对齐方式不会执行任何的对齐方式。