msgpack.packb()比pickle.dumps()更适合网络传输,因其输出纯二进制、无python特有元信息,体积更小(如示例减少约52%)、跨语言兼容且无代码执行风险;而pickle含运行时上下文,体积大且不安全。

用 msgpack 替代 pickle 是最直接有效的做法,尤其在微服务间高频通信场景下,序列化体积可减少 30%–50%,反序列化耗时通常降低 20% 以上。
为什么 msgpack.packb() 比 pickle.dumps() 更适合网络传输
msgpack 输出纯二进制、无 Python 特定元信息,不携带类名、模块路径或代码执行指令;而 pickle 的协议版本(如 protocol=5)虽已优化,仍包含大量运行时上下文,导致体积膨胀且无法跨语言解析。
- 相同字典
{"user_id": 123, "tags": ["a", "b"], "ts": 1725289080},pickle.dumps(..., protocol=5)输出约 128 字节,msgpack.packb(...)仅约 62 字节 -
msgpack.unpackb(data, raw=False)默认将字节串转为str,避免手动 decode;raw=True则返回bytes,适用于需要保留原始编码的场景(如嵌套二进制字段) - 若对象含
datetime、Decimal或自定义类型,msgpack需显式传入default=...和ext_hook=...处理,否则抛TypeError: can not serialize 'datetime'
自定义类对象怎么用 msgpack 序列化
不能直接传实例给 msgpack.packb() —— 它不像 pickle 那样自动调用 __dict__ 或魔术方法。必须先转成 dict/list/tuple 等基础结构。
- 推荐在类中实现
to_msgpack()方法,显式控制字段导出逻辑(比如过滤敏感字段、格式化时间) - 反序列化时用
@classmethod def from_msgpack(cls, data):构造新实例,而非依赖__setstate__ - 避免在
default回调里做深拷贝或 I/O 操作,否则会拖慢序列化主线程
示例:
import msgpack
from datetime import datetime
class User:
def __init__(self, name, created_at):
self.name = name
self.created_at = created_at
def to_msgpack(self):
return {
"name": self.name,
"created_at": int(self.created_at.timestamp())
}
@classmethod
def from_msgpack(cls, data):
return cls(data["name"], datetime.fromtimestamp(data["created_at"]))
u = User("Bob", datetime.now())
packed = msgpack.packb(u.to_msgpack())
unpacked = msgpack.unpackb(packed, raw=False)
restored = User.from_msgpack(unpacked)
遇到 TypeError: can not serialize 'set' 怎么办
msgpack 原生不支持 set、complex、memoryview 等类型,报错位置往往在嵌套结构深层,不容易一眼定位。
- 先用
print(type(obj), obj)快速检查待序列化对象的顶层类型,再逐层 inspect 其属性 - 统一用
default参数接管:例如default=lambda x: list(x) if isinstance(x, set) else None,但注意None会掩盖其他类型错误,建议按类型分支处理 - 更稳妥的方式是预处理:递归遍历对象,把所有
set转list,datetime转int或str,再交给msgpack.packb()
真正难处理的不是“怎么序列化”,而是“哪些字段不该序列化”——比如数据库连接、线程锁、回调函数引用。这些一旦漏掉检查,msgpack 不会报错,但会在反序列化端引发隐晦的 AttributeError 或逻辑错乱。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











