尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

056、pickle 与序列化:安全性警告、协议版本、替代方案 json、msgpack

056、pickle 与序列化:安全性警告、协议版本、替代方案 json、msgpack
📅 发布时间:2026/6/26 18:15:19

056、pickle 与序列化:安全性警告、协议版本、替代方案 json、msgpack

上周帮一个同事排查线上服务崩溃的问题,日志里只留下一行AttributeError: Can't get attribute 'OldModel' on <module '__main__' from ...>。一看就是 pickle 反序列化时类定义变了。这种坑我踩过不止一次,今天干脆把 pickle 的底裤扒干净,顺便聊聊什么时候该换 json 或 msgpack。

序列化到底在干什么

说白了就是把内存里的 Python 对象变成字节流,存文件、发网络、塞 Redis。反过来叫反序列化。pickle 是 Python 自带的,能序列化几乎任何对象——函数、类实例、甚至你自定义的迭代器。但代价就是它只认 Python,而且不安全。

那个让我加班的坑:协议版本

Python 2 时代默认是 protocol 0,文本格式,慢且体积大。Python 3 默认升到 protocol 3,但不同版本之间不总是兼容。我那个同事的坑是这样的:他用 Python 3.8 的 pickle 序列化了一个自定义类的实例,存到 Redis。后来代码重构,类名从OldModel改成了NewModel,反序列化时 pickle 找不到OldModel的定义,直接崩了。

别这样写:直接用默认 protocol 跨版本传输。如果你要长期存储 pickle 文件,或者在不同 Python 小版本间传递,显式指定 protocol 版本:

importpickle# 这里踩过坑:protocol 5 是 Python 3.8+ 才有的# 如果下游是 3.6,直接炸data=pickle.dumps(obj,protocol=4)# 保守点用 4,兼容 3.4+

protocol 版本对照表记一下:

  • 0: 文本格式,最慢,Python 2.3+
  • 1: 二进制格式,Python 2.3+
  • 2: Python 2.3+
  • 3: Python 3.0+,默认
  • 4: Python 3.4+,支持大对象
  • 5: Python 3.8+,支持 out-of-band data

个人建议:跨版本存储一律用 protocol 4,除非你确定所有环境都是 3.8+。

安全性警告:别信外部数据

这是最要命的。pickle 反序列化时会执行任意代码。你从网上、用户输入、甚至内部不信任的服务收到 pickle 数据,直接pickle.loads()等于把服务器钥匙交给别人。

importpickleimportos# 恶意构造的 pickle 数据classEvil:def__reduce__(self):return(os.system,('rm -rf /',))malicious_data=pickle.dumps(Evil())# 这行执行后,你的服务器可能就没了pickle.loads(malicious_data)

别这样写:永远不要对不可信数据用 pickle。内部服务之间用 pickle 也要加白名单或签名。我见过有人把 pickle 数据直接暴露在 HTTP API 里,结果被扫到直接 RCE。

替代方案:json 和 msgpack

json:安全但有限

json 只能序列化基本类型:dict、list、str、int、float、bool、None。自定义对象需要自己写 encoder/decoder。

importjsonfromdatetimeimportdatetimeclassCustomEncoder(json.JSONEncoder):defdefault(self,obj):ifisinstance(obj,datetime):returnobj.isoformat()# 这里踩过坑:忘了抛 TypeError 会导致无限递归returnsuper().default(obj)data={'time':datetime.now(),'name':'test'}json_str=json.dumps(data,cls=CustomEncoder)

json 的好处是跨语言、人类可读、安全。坏处是体积大、不支持 bytes、不支持复杂对象。

msgpack:折中方案

msgpack 像 json 的二进制版本,体积小、速度快、支持 bytes。需要装第三方库msgpack。

importmsgpack data={'name':'test','score':95.5,'tags':[1,2,3]}packed=msgpack.packb(data)# 二进制,比 json 小 30% 左右unpacked=msgpack.unpackb(packed)

msgpack 支持自定义类型,但需要写 hook:

importmsgpackfromdatetimeimportdatetimedefencode_datetime(obj):ifisinstance(obj,datetime):return{'__datetime__':True,'value':obj.isoformat()}returnobjdefdecode_datetime(obj):if'__datetime__'inobj:returndatetime.fromisoformat(obj['value'])returnobj packed=msgpack.packb(datetime.now(),default=encode_datetime)unpacked=msgpack.unpackb(packed,object_hook=decode_datetime)

个人建议:内部服务间通信优先用 msgpack,性能好、体积小、安全。对外 API 用 json,兼容性好。只有当你确定数据只在 Python 内部流转、且需要序列化复杂对象(比如函数、类实例)时,才考虑 pickle。

实战经验总结

  1. 永远不要用 pickle 做网络传输。我见过太多人图方便把 pickle 塞进 Redis 或 RabbitMQ,结果版本升级时全崩。用 msgpack 或 json 加自定义序列化,前期多写几行代码,后期少熬几个夜。

  2. pickle 只适合本地缓存或进程间通信。比如你训练了一个机器学习模型,用 pickle 存到本地文件,下次加载。但注意模型类定义不能变,否则反序列化失败。我一般会在 pickle 文件里加个版本号:

importpickleclassModelV1:def__init__(self,params):self.version=1self.params=params# 存的时候model=ModelV1({'lr':0.01})pickle.dump(model,open('model.pkl','wb'))# 加载的时候检查版本loaded=pickle.load(open('model.pkl','rb'))ifloaded.version!=1:raiseValueError('模型版本不匹配')
  1. 如果非要用 pickle,加签名。用 hmac 对 pickle 数据做签名,反序列化前验证,防止篡改。

  2. msgpack 的坑:它不支持set类型,序列化时会变成 list。如果你需要 set,自己转一下。另外 msgpack 的unpackb默认返回 dict,如果你需要有序字典,用object_pairs_hook=collections.OrderedDict。

  3. 性能对比:我压测过,序列化 1MB 的 dict,pickle 约 0.5ms,msgpack 约 0.3ms,json 约 0.8ms。反序列化 pickle 约 0.4ms,msgpack 约 0.2ms,json 约 0.6ms。msgpack 在体积和速度上都有优势。

最后说一句:序列化方案选型,先想清楚你的数据要活多久、要跨多少语言、要面对多少安全威胁。别让 pickle 成为你系统的后门。

相关新闻

  • 如何快速掌握Sketchfab模型下载:3D爱好者的完整实践指南
  • 免费跨平台绘图神器:draw.io桌面版完整使用指南
  • BetterNCM安装器:3分钟搞定网易云音乐插件一键安装的终极指南

最新新闻

  • 用友NC命令执行漏洞批量挖掘框架设计与实战
  • 【零基础AI应用开发】第02章:项目初始化与 Next.js 基础(入门篇)
  • 紫光FPGA独立仿真FIFO
  • Spring三大注入注解深度拆解:@Autowired、@Resource、@RequiredArgsConstructor 原理、示例、场景选型、面试全解
  • KPI定了、任务分了,而目标和执行差了十万八千里,企业计划、项目该如何落地?
  • IPXWrapper终极指南:在Windows 10/11上轻松运行经典IPX游戏

日新闻

  • Qwen2.5-Turbo百万上下文实战指南:百炼平台长文本处理全解析
  • 怎么监控对标账号更新,2026年作者监控工作流,5款深度对比
  • EdgeRemover:专业级Windows Edge浏览器管理工具,彻底解决顽固软件卸载难题

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号