python中常用的序列化模块_json、pickle、yaml、msgpack性能对比

6次阅读

json快但功能受限,仅支持str、intFloatbool、None、list、dict七种类型,遇datetime等会抛TypeError;实操中可用default参数转ISO字符串,避免深拷贝。

python中常用的序列化模块_json、pickle、yaml、msgpack性能对比

json.dumps/json.loads 为什么快但功能受限

jsonpython 标准库中序列化速度最快、兼容性最广的模块,但只支持 strintfloatboolNonelistdict 这七种类型。遇到 datetimeset、自定义类实例时会直接抛出 TypeError: Object of type ... is not JSON serializable

实操建议:

立即学习Python免费学习笔记(深入)”;

  • default 参数配合 isinstance 手动转 datetime 为 ISO 字符串(注意时区)
  • 避免在 default 中做深拷贝或递归处理,否则性能断崖下跌
  • 生产环境高频小数据(如 API 响应)优先选 json,别为了“看起来高级”换其他模块

pickle.dumps/pickle.loads 的安全与兼容陷阱

pickle 能序列化几乎所有 Python 对象,包括函数、类实例、闭包,但它是 Python 特有协议,跨语言不可读;更关键的是,pickle.loads() 可执行任意代码 —— 任何来自不可信源的 pickle 数据都等同于远程代码执行漏洞。

实操建议:

立即学习Python免费学习笔记(深入)”;

  • 永远不在网络传输、用户上传、日志回放等场景用 pickle
  • 若必须本地持久化(如缓存中间计算结果),限定使用 protocol=4(Python 3.4+ 默认),它比 protocol=3 小 10–20%,且支持更多内置类型
  • __reduce__ 方法可被恶意利用,自定义类若需支持 pickle,务必检查其返回值是否可控

yaml.safe_dump/yaml.safe_load 为何又慢又重

PyyAMLsafe_load 看似安全,但实际解析器仍存在历史 CVE(如 CVE-2017-18342),且默认启用复杂解析逻辑(锚点、标签、自动类型推断),导致性能远低于 json。一个 100KB 的纯字典数据,yaml.safe_load 可能比 json.loads 慢 5–8 倍。

实操建议:

立即学习Python免费学习笔记(深入)”;

  • 除非明确需要 YAML 特性(如注释、多文档、锚引用),否则别用 yaml 做通用序列化
  • 禁用自动类型转换:传入 Loader=yaml.CLoader(需编译安装 libyaml)和 yaml.load(..., Loader=yaml.CSafeLoader)
  • 配置文件yaml,运行时数据交换别碰它

msgpack.packb/msgpack.unpackb 的二进制优势与隐含成本

msgpack 是唯一在性能、体积、跨语言支持上全面优于 json 的选择:相同数据通常小 30–50%,序列化/反序列化快 2–4 倍。但它默认不保留 key 顺序(Python 3.7+ dict 有序,但 msgpack 不保证),且 datetime 需显式开启 datetime=True 参数,否则变成时间戳整数。

实操建议:

立即学习Python免费学习笔记(深入)”;

  • 安装时加 ujsonmsgpack 的 C 扩展:pip install msgpack --no-binary msgpack
  • 服务间通信、redis 缓存、日志批量写入等场景,优先测 msgpack + use_bin_type=True
  • 不要依赖 msgpack.unpackb(data, raw=False) 自动转 bytesstr,Python 3 下易引发编码歧义

真正影响选型的往往不是“谁最快”,而是“谁在你的数据结构、部署环境、上下游约束下不出错”。比如用 msgpacknumpy.ndarray,得额外配 ext_hook;而 json 明知慢,却因浏览器直读、cdn 缓存友好,成了事实标准。选模块前,先跑一遍你的真实数据样本,用 timeit 测三轮,比看任何 benchmark 都管用。

text=ZqhQzanResources