解码打包数据到结构中

6 投票
5 回答
12712 浏览
提问于 2025-04-15 16:52

如何将一个Python字符串拆分成多个字段?

我从一个TCP套接字接收到了一些数据,这些数据是以特定的方式打包的,我想它会以字符串的形式从套接字的接收函数中得到。

它的格式如下:

uint8 - 头部
uint8 - 长度
uint32 - 类型ID
uint16 - 参数1
uint16 - 参数2
uint16 - 参数3
uint16 - 参数4
char[24] - 名称字符串
uint32 - 校验和
uint8 - 尾部

(我还需要拆分其他格式不同的数据包)

我该如何拆分这些数据呢?

我刚开始学Python,之前学过一点'C'语言。如果我用'C'语言的话,可能会用结构体,那在Python中也可以这样做吗?

祝好

X

5 个回答

4

这是对你提问的一个回答:

这肯定不是最好的方法,因为它根本不管用。struct.unpack() 总是返回一个元组。如果你想从这个元组中提取出单个项,你需要这样做:要么用 field1 = struct.unpack('B',data[0])[0],要么用 field1, = struct.unpack('B',data[0])

即使这样修正了,这也不是个好方法:输入的内容太多,容易出错的[start:end],而且调用了10次函数而不是一次,效率也不高。

因为你有名字,你可以用这些名字代替field1或者field[0],这样做会更好:

(header, length, typeID, param1, param2,
param3, param4, name_string, checksum, footer,
) = struct.unpack("!2B I 4H 24s I B", data)
4

使用 struct 模块

7

struct模块的设计目的是根据格式字符串将不同类型的数据解包成一个元组。一次性解包整个结构体比一个字段一个字段地提取要更合理。下面是一个例子:

fields = struct.unpack('!BBI4H20sIB', data)

然后你可以访问某个特定的字段,比如第一个字段:

fields[0]

你还可以用这个元组来初始化一个命名元组(NamedTuple);可以查看struct的文档来获取示例。命名元组只在Python 2.6及以上版本可用,它们的行为更像Python的结构体,你可以像访问属性一样访问元素,比如fields.header。当然,如果你愿意,也可以通过写一个类来封装元组中的信息,这样做会稍微复杂一些……不过如果你不在意的话,直接索引字段就可以了,正如我上面所示的那样。

撰写回答