python3 利用struct.pack 动态组建字节流

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python3 利用struct.pack 动态组建字节流相关的知识,希望对你有一定的参考价值。

使用struct.pack需要一个一个指定参数,但是,如果我的参数个数不固定,需要动态改变,比如需要写入不多个0xff,该怎么实现?如果不用struct.pack的话,有什么其他办法。

a = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
fmt = str(len(a)) + 'H' # 默认小端模式
struct.pack(fmt, *a) # 列表a前面加*,表示将a解压后单个传入参数
推理:a如果是动态变化的list,或者动态截取a其中一段来转换成字节流都是可以的
参考技术A 序列化写数据流时,应该用python的IO工具。struck.pack只作为单个数据的序列化过程。
比如文件

file=open(......
file.write(struck.pack(..........));
file.write(struck.pack(..........));
或者内存
f = io.BytesIO()
f.write(struck.pack(..........))
f.write(struck.pack(..........))本回答被提问者采纳

msgpack 能否提供更好的性能和与 python 的 struct.pack() 相同的功能?

【中文标题】msgpack 能否提供更好的性能和与 python 的 struct.pack() 相同的功能?【英文标题】:can msgpack provide better performance and identical functionality of python's struct.pack()? 【发布时间】:2018-09-02 00:03:55 【问题描述】:

post 比较了许多序列化例程,表明 msgpack 比 Python 的 struct.pack() 和 unpack() 例程更快。我想使用 msgpack,但不知道如何以与 struct.pack() 等效的方式将 msgpack.packb() 用于浮点数或双精度数。

我需要通过 udp 从 python 将 N 个 double 发送到一个通过 udp/ip 读取 N 个 double 的 C/C++ 侦听器。无法修改 C/C++ 侦听器。 Python struct.pack() 方法与此剪辑一样适用于打包 N=3 双打:

import struct
import msgpack

packer = struct.Struct('ddd')
myTuple = (1.1, 2.2, 3.3)
packedData = packer.pack(*myTuple)

print(packedData) 产量:

b'\x9a\x99\x99\x99\x99\x99\xf1?\x9a\x99\x99\x99\x99\x99\x01@ffffff\n@'

然后用 msgpack 尝试同样的事情:

msgPackedData = msgpack.packb(myTuple)

和 print(msgPackedData) 产生:

b'\x93\xcb?\xf1\x99\x99\x99\x99\x99\x9a\xcb@\x01\x99\x99\x99\x99\x99\x9a\xcb@\nffffff'

输出显然不一样。使用 struct.pack() 发送的数据包被 udp 监听器完美地解释,但我想获得 msgpack 的性能改进。

在产生与struct.pack() 相同的输出时,能否获得 msgpack 的性能?

【问题讨论】:

【参考方案1】:

让我们比较两个打包的二进制文件。

上排是msgPackedData,下排是packedData

0x93 0xcb 0x3f 0xf1 0x99 0x99 0x99 0x99 0x99 0x9a 0xcb 0x40 0x01 0x99 0x99 0x99 0x99 0x99 0x9a 0xcb 0x40 0x0a 0x66 0x66 0x66 0x66 0x66 0x66 
          0x9a 0x99 0x99 0x99 0x99 0x99 0xf1 0x3f      0x9a 0x99 0x99 0x99 0x99 0x99 0x01 0x40      0x66 0x66 0x66 0x66 0x66 0x66 0x0a 0x40 

可以看到第一个 0x93 和三个 0xcb。这是什么?

MessagePack 包含类型信息。

0x93 表示 3 个元素的数组。 https://github.com/msgpack/msgpack/blob/master/spec.md#array-format-family

0xcb 表示大端 IEEE 754 双精度浮点数https://github.com/msgpack/msgpack/blob/master/spec.md#float-format-family

因此msgPackedDatapackedData 大4 个字节。

packedDatamsgPackedData 之间的另一个区别是字节顺序。但不影响大小。

如果您不使用元组,而只是打包三个双精度数,那么您可以删除第一个 0x93。但是没有办法删除0xcb。这是MessagePack格式中唯一的双数表达方式。

【讨论】:

所以答案是,不,没有办法使用 msgpack 生成与 'struct.pack()' 等效的输出?我很惊讶二进制和原始等选项不能提供相同结果的方法 似乎msgpack的性能优势只有在两端打包和解包时才能实现 正如您所评论的,答案是“否”。看来我们在使用struct.pack()的时候,需要知道完整的类型信息,而且两端都要匹配。 msgpack 是不同的。它包含 JSON 等类型信息。如果接收端不知道内容,他们可以在一定程度上处理数据。例如创建 JSON 输出。我认为,如果您选择 msgpack 作为高效 JSON 之类的东西,那就太好了。见msgpack.org。如果要最小的打包方式,msgpack 是不行的。我认为这是一种灵活性/尺寸选择。

以上是关于python3 利用struct.pack 动态组建字节流的主要内容,如果未能解决你的问题,请参考以下文章

qt中如何解包利用python 的struct.pack()函数打包的数据

Arduino 和 Python (3.x) 之间的 Serial.read() 和 Struct.pack / 串行通信问题

python struct.pack方法报错argument for 's' must be a bytes object 解决

Python里 int 和 bytes互转的方法

Python struct.pack() 行为

如何通过 Modbus TCP 使用“struct.pack”类型发送?