4.1.2.3 格式字符例子

采用小端模式进行解包,并赋值例子:

#python 3.4.3
import struct

record = b'raymond   \x32\x12\x08\x01\x08'
name, serialnum, school, gradelevel = struct.unpack('<10sHHb', record)
print(name, serialnum, school, gradelevel)

结果输出如下:

b'raymond   ' 4658 264 8

在这里采用struct.unpack解包,把记录record二进制流进行分解,把四项数据保存在name, serialnum, school, gradelevel里面,最后把它们显示出来。其中'<10sHHb'是表示采用小端模式,10个字符,两个无符号数,一个有符号字符类型。

 

采用命名元组保存解包的数据例子:

#python 3.4.3
import struct
from collections import namedtuple

record = b'raymond   \x32\x12\x08\x01\x08'
name, serialnum, school, gradelevel = struct.unpack('<10sHHb', record)
print(name, serialnum, school, gradelevel)

Student = namedtuple('Student', 'name serialnum school gradelevel')
#解包数据保存到元组
print(Student._make(struct.unpack('<10sHHb', record)))

结果输出如下:

b'raymond   ' 4658 264 8

Student(name=b'raymond   ', serialnum=4658, school=264, gradelevel=8)

在这个例子里,主要使用namedtuple,然后直接调用_make方法,把解包出来的数据,直接保存在命名元组里,不需要创建新的变量保存数据,对于数据的结构化管理很方便。相当二进制流过来解包,直接生成一个结构化的元组。

 

默认数据对齐方式的例子:

#python 3.4.3

import struct

 

print('ci:', struct.pack('ci', b'*', 0x12131415))

print('ic:', struct.pack('ic', 0x12131415, b'*'))

print('ci size:', struct.calcsize('ci'))

print('ic size:', struct.calcsize('ic'))

结果输出如下:

ci: b'*\x00\x00\x00\x15\x14\x13\x12'

ic: b'\x15\x14\x13\x12*'

ci size: 8

ic size: 5

从这个例子里,可以看到同样是两个类型ci的格式,只是排列不一样,导致最后打包出来的二进制流大小不一样,就是由于在连续两个类型之间会产生补齐字符的情况。如果在同一个主机或者同一台电脑里使用下,对于是否添加补充字符是一样的,对于不同的电脑可能是不一样的。所以一般来说对于不同电脑之间的通讯,就需要采用不补充的方式进行填充了,把例子修改如下:

#python 3.4.3

import struct

 

print('=ci:', struct.pack('=ci', b'*', 0x12131415))

print('=ic:', struct.pack('=ic', 0x12131415, b'*'))

print('=ci size:', struct.calcsize('=ci'))

print('=ic size:', struct.calcsize('=ic'))

结果输出如下:

=ci: b'*\x15\x14\x13\x12'

=ic: b'\x15\x14\x13\x12*'

=ci size: 5

=ic size: 5

 

以四字对齐,在结构后尾补齐的例子:

#python 3.4.3

import struct

 

print('llh:', struct.pack('llh', 1, 2, 3))

print('llh0l:', struct.pack('llh0l', 1, 2, 3))

print('llb0l:', struct.pack('llh0l', 1, 2, 3))

结果输出如下:

llh: b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00'

llh0l: b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'

llb0l: b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00'

在这个例子里,通过格式串后尾添加零个l的方式来进行四字节对齐,要注意这里格式字符l,而不是数字1

4.1.3 struct

struct模块里,定义一个类struct,主要以下方法:

class struct.Struct(format)

返回一个可以按格式format进行操作二进制数据的Struct对象。如果只有一种格式进行解包和打包时,采用此对象比使用函数更高效,因为格式字符串只需要进行处理一次,就可以对不同数据进行解包和打包的操作了。

此对象支持以下方法和属性:

pack(v1, v2, ...) 

pack()函数功能一样,用已经编译好的格式字符串打包。

 

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

pack_into()函数功能一样,用已经编译好的格式字符串打包。

 

unpack(buffer) 

unpack()函数功能一样,用已经编译好的格式字符串解包。

 

unpack_from(buffer, offset=0) 

unpack_from()函数功能一样,用已经编译好的格式字符串解包。

 

iter_unpack(buffer) 

iter_unpack()函数功能一样,用已经编译好的格式字符串解包。

 

format 

保存构造时传入格式字符串。

 

size 

根据格式字符串进行计算出来需要二进制缓冲区的大小。

例子:

#python 3.4.3

import struct

 

fmt = struct.Struct('llh')

print(fmt.format)

print(fmt.size)

 

encode = fmt.pack(1, 2, 3)

print(encode)

print(fmt.unpack(encode))

结果输出如下:

b'llh'

10

b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00'

(1, 2, 3)

 

蔡军生  QQ:9073204  深圳

你可能感兴趣的:(struct,python,二进制,网络协议,milang)