python - struct

来源:互联网 发布:程序员入门学什么 编辑:程序博客网 时间:2024/06/07 02:52

描述

引用Python官网介绍 struct 的一段话.

"This module performs conversions between Python values and C structs represented as Python strings. This can be used in handling binary data stored in files or from network connections, among other sources. It usesFormat Strings as compact descriptions of the layout of the C structs and the intended conversion to/from Python values."

大概的意思是: struct 模块主要用于,完成Python值与Python字符串代表的C结构的转换。它可以被用于文件、网络及其源的的二进制数据处理。该模块使用Format Strings描述C的结构类型以及Python的转入/转出。


功能

struct模块的主要函数与方法,如下表所示:

exception struct.errorstruct.pack(fmt, v1, v2, ...)struct.pack_into(fmt, buffer, offset, v1, v2, ...)struct.unpack(fmt, string)struct.unpack_from(fmt, buffer[, offset=0])struct.calcsize(fmt)
使用struct模块时,需要注意格式化字符串的机制,这个机制主要用于指定函数pack/unpack的字符串布局。参数中的fmt可以用于说明,已打包数据的byte order, size, alignment 这3个属性(请考虑系统结构对上述参数的影响)。

CharacterByte orderSizeAlignment@nativenativenative=nativestandardnone<little-endianstandardnone>big-endianstandardnone!network (= big-endian)standardnone
如果地一个参数不在列表当中,那么将启用@选项。上述参数外,我们还需要注意所提供字符的类型,C类型与Python类型对应表如下:

FormatC TypePython typeStandard sizeNotesxpad byteno value  ccharstring of length 11 bsigned charinteger1(3)Bunsigned charinteger1(3)?_Boolbool1(1)hshortinteger2(3)Hunsigned shortinteger2(3)iintinteger4(3)Iunsigned intinteger4(3)llonginteger4(3)Lunsigned longinteger4(3)qlong longinteger8(2), (3)Qunsigned longlonginteger8(2), (3)ffloatfloat4(4)ddoublefloat8(4)schar[]string  pchar[]string  Pvoid *integer (5), (3)
Standard size,表示字节数。

fmt参数 = character + Format


1、pack和unpack

struct提供用format specifier方式对数据进行打包和解包(Packing and Unpacking)。

struct.pack(fmt, v1, v2, ...)
Return a string containing the values v1, v2, ... packed according to the given format. The arguments must match the values required by the format exactly.

struct.unpack(fmt, string)
Unpack the string (presumably packed by pack(fmt,...)) according to thegiven format. The result is a tuple even if it contains exactly one item.The string must contain exactly the amount of data required by the format(len(string) must equal calcsize(fmt)).

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

'hhl' 表示需要打包的格式,
1,2,3 表示打包的数据。
calcsize函数,用于计算hhl格式所需的字节大小


2、pack_into和unpack_from

 使用二进制打包数据的场景大部分都是对性能要求比较高的使用环境。而在上面提到的pack方法都是对输入数据进行操作后重新创建了一个内存空间用于返回,也就是说我们每次pack都会在内存中分配出相应的内存资源,这有时是一种很大的性能浪费。struct模块还提供了pack_into() 和 unpack_from()的方法用来解决这样的问题,也就是对一个已经提前分配好的buffer进行字节的填充,而不会每次都产生一个新对象对字节进行存储。

struct.pack_into(fmt, buffer, offset, v1, v2, ...)
Pack the values v1, v2, ... according to the given format, write thepacked bytes into the writablebuffer starting at offset. Note that theoffset is a required argument.

struct.unpack_from(fmt, buffer[, offset=0])
Unpack the string (presumably packed by pack(fmt,...)) according to thegiven format. The result is a tuple even if it contains exactly one item.The string must contain exactly the amount of data required by the format(len(string) must equal calcsize(fmt)).


+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

importstruct
importbinascii
importctypes
 
values=(1,'abc',2.7)
s=struct.Struct('I3sf')
prebuffer=ctypes.create_string_buffer(s.size)
print'Before :',binascii.hexlify(prebuffer)
s.pack_into(prebuffer,0,*values)
print'After pack:',binascii.hexlify(prebuffer)
unpacked=s.unpack_from(prebuffer,0)
print'After unpack:',unpacked
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

输出:

Before : 000000000000000000000000
After pack: 0100000061626300cdcc2c40
After unpack: (1, 'abc', 2.700000047683716)

对比使用pack方法打包,pack_into 方法一直是在对prebuffer对象进行操作,没有产生多余的内存浪费。另外需要注意的一点是,pack_into和unpack_from方法均是对string buffer对象进行操作,并提供了offset参数,用户可以通过指定相应的offset,使相应的处理变得更加灵活。例如,我们可以把多个对象pack到一个buffer里面,然后通过指定不同的offset进行unpack:

import struct
import binascii
import ctypes
 
values1 =(1,'abc',2.7)
values2 =('defg',101)
s1 =struct.Struct('I3sf')
s2 =struct.Struct('4sI')
 
prebuffer =ctypes.create_string_buffer(s1.size+s2.size)
print 'Before :',binascii.hexlify(prebuffer)
s1.pack_into(prebuffer,0,*values1)
s2.pack_into(prebuffer,s1.size,*values2)
print 'After pack:',binascii.hexlify(prebuffer)
print s1.unpack_from(prebuffer,0)
print s2.unpack_from(prebuffer,s1.size)

输出:

Before : 0000000000000000000000000000000000000000
After pack: 0100000061626300cdcc2c406465666765000000
(1, 'abc', 2.700000047683716)
('defg', 101)



推荐阅读: https://docs.python.org/2.7/library/struct.html
0 0