Python 二进制结构化数据处理和封装

当 python 需要调用 C 程序,或是进行文件、网络操作时,需要对二进制结构化字节流进行处理,此时需要使用到 struct 这个模块提供的方法。 详细方法可以查看 官方教程

当 python 需要调用 C 程序,或是进行文件、网络操作时,需要对二进制结构化字节流进行处理,此时需要使用到 struct 这个模块提供的方法。

详细方法可以查看 官方教程,这里以 perlpack 作为对比,使用 python 实现类似 perl 数据打包的效果。

在 perl 的 pack 方法中,提供了一种 Z* 的写法,可以总是保证最后有一位空填充,在 python 中则可以这样实现:

1
2
3
4
# 类比 perl 的 pack "VVVVZ*", $max, 0, 0, 0, $user;
fmt = "<4lx" + str(len(user) + 1) + "s" # 类比 perl Z*,总是保证最后有一位空填充
bindata = struct.pack(fmt, maxn, 0, 0, 0, bytes(user, encoding="utf8"))
# 小端序,4个 long (32位整) 后面跟 填充字节 ,然后再拼 字符长度 +1 个 s(字节串)

最后打印出来的效果是这样:

1
b'tasklist\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00dev\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'

如果直接使用 .format 或是字符拼接 + ``.ljust(256, ‘\000’)之类的方法在后面强行补0` 也是可以实现类似的效果,但是打印出来还是字符对象,不是我希望的字节流对象,而且很繁琐,不专业:

1
'tasklist                                                                                                                                                                                                                                                        dev                                                                                                                                                                                                                                                             '

大概就是这样,像是中间塞了一堆空格。建议数据打包还是使用 struct.pack 来进行。

基本实现需求。

参考文献


Python 二进制结构化数据处理和封装
https://www.frytea.com/post/20220118000448.html
作者
Tianlun Song
发布于
2022年1月18日
更新于
2024年6月10日
许可协议