python struct中pack和unpack

本文详细介绍了Python struct的pack和unpack方法的用途,以及如何使用它们进行二进制数据的序列化和反序列化。通过实例展示了如何正确设置format字符串以获取特定的数据类型,并解释了如何确定读取数据的类型。此外,文章还讨论了字节序的概念及其对数据解释的影响,以及如何使用struct处理网络字节流。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

python struct的中pack和unpack方法,其实是外界通信的一种方式;

其实就是序列化和反序列化;

pack: 序列化,将python的数据类型表示为外界可认知的数据类型;

unpack: 反序列化, 将外界的数据类型转化Python的数据类型;


需要注意两点:

1.  数据类型的对应关系;

2.  数据类型表示的字节序问题;


python的format串与c的数据type的类型对应关系(参见python doc):

FormatC TypePythonNotes
xpad byteno value 
ccharstring of length 1 
bsigned charinteger 
Bunsigned charinteger 
hshortinteger 
Hunsigned shortinteger 
iintinteger 
Iunsigned intlong 
llonginteger 
Lunsigned longlong 
qlong longlong(1)
Qunsigned long longlong(1)
ffloatfloat 
ddoublefloat 
schar[]string 
pchar[]string 
P void * integer

字节序表示方法:

FormatC TypePythonNotes
xpad byteno value 
ccharstring of length 1 
bsigned charinteger 
Bunsigned charinteger 
hshortinteger 
Hunsigned shortinteger 
iintinteger 
Iunsigned intlong 
llonginteger 
Lunsigned longlong 
qlong longlong(1)
Qunsigned long longlong(1)
ffloatfloat 
ddoublefloat 
schar[]string 
pchar[]string 
P void * integer





这两天做TCP协议,数据的传输都是二进制的,需要解析,

于是用到了struct 看到这样一句代码:
  

Python代码  收藏代码
  1. length = struct.unpack('>I'self.buffer[:4])[0]  

 

当时没有明白format=">I"是什么意思,从google找了一下,有人说这个东西,可都是比较笼统,没能让我明白,

于是硬着头皮看API:
By default, C numbers are represented in the machine’s native format and byte order, 

and properly aligned by skipping pad bytes if necessary (according to the rules used by the C compiler).
通常,C语言下数字都是机器语言的格式并且按照字节排序,

同时在需要的情况下会利用跳过填补的字节来进行适当的调整

 

Alternatively, the first character of the format string can be used to indicate the byte order, size and alignment of the packed data。
非此即彼:字符串的第一个字符要么被用于表示字符串的字节的排序,

或者是字符串的size,还有就是数据是否对准。


 

Native byte order is big-endian or little-endian, depending on the host system. 

For example, Motorola and Sun processors are big-endian; Intel and DEC processors are little-endian.
计算机的字节序要么是高位顺序,要么是低位的,这依赖于主机本身。

比如,摩托罗拉和sun的处理器是高位的,但是intel和DEC的是低位的。

 

这样子就明白了

上面的format=">I"的意思,也就是说按照高位顺序来格式化取得一个int或long值。

下面问题就又来了,你怎么知道读取的就是一个int或long值呢?

通过看struct的文档,可以看到struct通过两张表制定了一定的format规则,

我按照自己的观察,给他归纳为两类,一个是和C当中类型的对照,

另一个就是选择按照高位还是低位来解释字节。上面已经说了高低字节顺序,那么观察和C对照的表格,发现I 代表的就是integer or long ,详细的可以去看python的API。


python的format串与ctype的类型对应关系(参见python doc):

FormatC TypePythonNotes
xpad byteno value 
ccharstring of length 1 
bsigned charinteger 
Bunsigned charinteger 
hshortinteger 
Hunsigned shortinteger 
iintinteger 
Iunsigned intlong 
llonginteger 
Lunsigned longlong 
qlong longlong(1)
Qunsigned long longlong(1)
ffloatfloat 
ddoublefloat 
schar[]string 
pchar[]string 
P void * integer

 

下面是一些使用的例子,具体的使用,可以参考这些例子:
1. 设置fomat格式,如下: 
# 取前5个字符,跳过4个字符华,再取3个字符 

 # 取前5个字符,跳过4个字符华,再取3个字符 
 format = '5s 4x 3s'



2. 使用struck.unpack获取子字符串 

import struct 

format = '5s 4x 3s'
print struct.unpack(format, 'Test astring') 
#('Test', 'ing') 


来个简单的例子吧,

有一个字符串'He is not very happy',处理一下,把中间的not去掉,然后再输出。 

import struct 
theString = 'He is not very happy' 
format = '2s 1x 2s 5x 4s 1x 5s' 
print ' '.join(struct.unpack(format, theString)) 
输出结果: 
He is very happy

 

 

关于网络字节的东东,从网上看来的,感觉有用:

Python的socket库采用二进制串来来编码待发送和接收的数据,

这样当我们用
i = socket.recv(4) 来接收一个4字节的整数时,

该整数实际上是以二进制的形式保存在字符串 i 的前4个字节中;

大多数的时候我们需要的是一个真正的integer/long型,

而不是一个用string型表示的整型。


这时我们可以使用struct库:Interpret

strings as packed binary data. 对上面的情况,

我们可以写
t = unpack("I", i)

第一个参数是格式化字符串,I指明字符串 i 包含的头一个数据项,是一个以C语言的unsigned integer表示的整数,

这里 i 只包含了一个数据项,

实际上这个被解释的字符串也可以包含多个数据项,

只要在格式化字符串里为每项数据指明一个格式即可;

自然地,unpack返回的就是一个tuple类型了。




FormatC TypePythonNotes
xpad byteno value 
ccharstring of length 1 
bsigned charinteger 
Bunsigned charinteger 
hshortinteger 
Hunsigned shortinteger 
iintinteger 
Iunsigned intlong 
llonginteger 
Lunsigned longlong 
qlong longlong(1)
Qunsigned long longlong(1)
ffloatfloat 
ddoublefloat 
schar[]string 
pchar[]string 
P void * integer
struct库是Python中用于处理二进制数据的模块。它提供了packunpack函数来执行二进制数据的打包解包操作。 pack函数的作用是将Python对象按照指定的格式转换为二进制字符串。它接受两个参数:格式字符串要打包的数据。格式字符串指定了要打包的数据的类型顺序,可以使用特定的格式字符来表示不同类型的数据,如整数、浮点数、字符串等。打包后的二进制字符串可以用于存储或传输。例如,使用"i"表示整数类型,使用"f"表示单精度浮点数类型unpack函数的作用是将二进制字符串解析为Python对象。它接受两个参数:格式字符串要解包的二进制字符串。根据格式字符串的指定,unpack函数将二进制数据解析为相应的Python对象,并返回一个元组,其中包含解析后的数据。例如,使用"i"表示整数类型,使用"f"表示单精度浮点数类型。 下面是一个示例: ```python import struct # 打包 data = struct.pack("if", 10, 3.14) print(data) # b'\n\x00\x00\x00\x1f\x85\xebQ' # 解包 unpacked_data = struct.unpack("if", data) print(unpacked_data) # (10, 3.140000104904175) ``` 在上面的示例中,我们使用格式字符串"if"对整数浮点数进行打包解包操作。打包后的二进制字符串为`b'\n\x00\x00\x00\x1f\x85\xebQ'`,解包后得到的元组为`(10, 3.140000104904175)`。 需要注意的是,格式字符串中的格式字符要打包/解包的数据类型要匹配,否则可能会导致数据错误或异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值