大家好,我是木木。
今天给大家分享一个紧凑的 Python 库,msgpack。
msgpack
msgpack 是 MessagePack 的 Python 实现。MessagePack 可以理解成一种二进制序列化格式,表达能力接近 JSON,但体积通常更小,解析也更适合机器传输。它常见于缓存值、RPC 消息、日志管道、跨语言数据交换和本地中间文件。相比 JSON,它的可读性弱一些,但在体积和类型表达上更灵活。用它时要重点约定 raw/bin、扩展类型和跨语言兼容策略。
项目地址:https://github.com/msgpack/msgpack-python
官方文档:https://msgpack-python.readthedocs.io/
三大特点
体积紧凑
二进制编码通常比 JSON 更省空间,适合高频传输和缓存。
跨语言好
MessagePack 有多语言实现,适合不同服务之间交换数据。
支持扩展
ExtType 能表达业务自定义类型,但需要团队提前约定。
最佳实践
安装方式:pip install msgpack。
第一段代码解决的问题是:把 Python dict 打包成 MessagePack bytes,再恢复成原始结构。
importmsgpackfromimportlib.metadataimportversionpayload={"name":"Alice","scores":[18,21],"active":True}packed=msgpack.packb(payload,use_bin_type=True)restored=msgpack.unpackb(packed,raw=False)print("package:",version("msgpack"))print("bytes:",len(packed))print("restored:",restored)
第二段代码解决的问题是:在一个字节流里连续写入多个对象,再用 Unpacker 逐个读取,适合日志和消息流。
importio,msgpackbuffer=io.BytesIO()packer=msgpack.Packer(use_bin_type=True)foritemin[{"id":1},{"id":2},{"id":3}]:buffer.write(packer.pack(item))buffer.seek(0)items=list(msgpack.Unpacker(buffer,raw=False))print("items:",items)print("count:",len(items))
环境与版本信息
本文示例使用 Python 3.11.0,msgpack 1.1.2。示例只做本地序列化和反序列化,不依赖网络服务。
高级功能
进阶一点看 ExtType。MessagePack 标准类型不直接表达 Decimal 这类业务对象,可以用扩展类型把它编码成 bytes,再在解码时恢复。关键是扩展码要在团队和跨语言服务之间保持一致。
importmsgpackfromdecimalimportDecimaldefdefault(obj):ifisinstance(obj,Decimal):returnmsgpack.ExtType(42,str(obj).encode())raiseTypeErrordefext_hook(code,data):ifcode==42:returnDecimal(data.decode())returnmsgpack.ExtType(code,data)packed=msgpack.packb({"price":Decimal("19.90")},default=default,use_bin_type=True)restored=msgpack.unpackb(packed,raw=False,ext_hook=ext_hook)print("price:",restored["price"])print("type:",type(restored["price"]).__name__)print("bytes:",len(packed))
适用场景
适合缓存值、消息队列 payload、RPC 数据、二进制日志、跨语言数据交换,以及需要比 JSON 更紧凑的本地中间文件。
不适用场景
不适合需要人工直接阅读和手改的数据文件、浏览器原生消费的公开 API,或团队无法统一扩展类型约定的系统。
上线检查
- 固定
raw=False 和 use_bin_type=True 这类关键选项,避免字符串和 bytes 混乱。 - 给跨语言 payload 写兼容测试,确认不同实现解码一致。
- 自定义 ExtType 要登记扩展码,避免不同业务类型撞码。
总结
msgpack 适合把结构化数据压得更紧凑。它不是为了替代所有 JSON,而是在传输和缓存这类机器读写场景里更有优势。