news 2026/4/30 3:51:03

Python 对象序列化与存储库pickle详细介绍

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python 对象序列化与存储库pickle详细介绍

一、pickle 是什么?

pickle是 Python 标准库中的对象序列化工具

  • 序列化(dumping / pickling):把内存中的 Python 对象(如列表、字典、自定义类实例等)转换成字节流(bytes),以便:
    • 写入文件
    • 通过网络发送
    • 存入缓存或数据库的二进制字段等
  • 反序列化(loading / unpickling):把字节流重新还原为原先的 Python 对象。

特点:

  • 支持大多数内置类型和自定义类实例。
  • 是 Python 专用的二进制协议,不同语言之间不通用
  • 默认协议不是可读文本(不是 JSON / YAML,而是二进制格式)。

适用场景:在 Python 环境内部保存/恢复复杂对象(如机器学习模型、缓存的中间结果、复杂数据结构等)。


二、基本接口与常用函数

1. 常用函数

importpickle# 写入/读取文件接口pickle.dump(obj,file,protocol=None)# 序列化到文件对象pickle.load(file)# 从文件对象反序列化# 操作 bytes 接口pickle.dumps(obj,protocol=None)# 序列化为 bytespickle.loads(data)# 从 bytes 反序列化
  • protocol:序列化协议版本,整数,一般用:
    • protocol=pickle.HIGHEST_PROTOCOL(推荐)
    • 不写时使用默认协议(不同 Python 版本默认值不同)

三、基础用法示例

1. 序列化到文件 / 从文件加载

importpickle data={"name":"Alice","age":25,"scores":[95,88,76],"active":True}# 写入文件(推荐使用二进制模式 'wb')withopen("data.pkl","wb")asf:pickle.dump(data,f,protocol=pickle.HIGHEST_PROTOCOL)# 从文件读取withopen("data.pkl","rb")asf:loaded_data=pickle.load(f)print(loaded_data)

说明:

  • 文件扩展名通常用.pkl.pickle.p,仅是约定,非强制。
  • 必须使用二进制模式"wb"/"rb"

2. 转换为 bytes / 从 bytes 恢复

importpickle obj=[1,2,3,{"a":10}]data_bytes=pickle.dumps(obj,protocol=pickle.HIGHEST_PROTOCOL)# 可以用于网络传输、缓存等restored=pickle.loads(data_bytes)print(restored)

四、pickle 支持哪些类型?

大多数常见类型都支持:

  • 基本类型:intfloatboolstrbytesNone
  • 容器类型:listtupledictsetfrozenset
  • 函数、类、实例(有一些限制,见后文)
  • datetimedecimal.Decimalfractions.Fraction等常用内置类型
  • 许多第三方库对象(如大部分sklearn模型)——库作者实现了对应的序列化协议

不太适合 / 有限制的对象:

  • 打开的文件对象、数据库连接、线程、进程、锁等与系统资源强绑定的对象:
    • 常常无法完全恢复原状态(反序列化时环境已不同)
  • lambda 匿名函数、内部函数、局部类等:普通pickle不能可靠处理(要用dill等扩展库)

五、pickle 协议(protocol)版本

protocol是决定如何编码对象为字节流的“格式版本”。

  • 常用写法:
    pickle.dump(obj,f,protocol=pickle.HIGHEST_PROTOCOL)
  • 查看当前解释器支持的最高协议:
    importpickleprint(pickle.HIGHEST_PROTOCOL)
  • 越新的协议:
    • 通常更高效、更紧凑
    • 但在旧版本 Python 上可能无法反序列化

跨 Python 版本使用 Pickle 时:

  • 如果你需要在不同 Python 版本间共享.pkl文件,建议:
    • 较低版本的 Python 中查看HIGHEST_PROTOCOL,然后在较高版本中固定使用该协议版本。
    • 或者使用更兼容的格式(如 JSON、msgpack 等)。

六、自定义类的 pickle 行为

1. 直接序列化自定义类实例

默认情况下,自定义类的实例是可以被 pickle 的:

importpickleclassPerson:def__init__(self,name,age):self.name=name self.age=age p=Person("Alice",25)# 序列化data=pickle.dumps(p)# 反序列化p2=pickle.loads(data)print(p2.name,p2.age)

要求:

  • 类定义在模块的顶层作用域(不是函数内部)。
  • 反序列化时,需要能找到同名模块和类定义,否则会失败:
    • 也就是说:Person类定义在mymodule.py中,那么加载 pickle 时环境里也要有mymodule.Person

2. 控制属性:__getstate____setstate__

如果你想:

  • 某些属性不参与序列化(如打开的文件句柄)
  • 序列化前/后做一些处理

可以在类中实现:

classPerson:def__init__(self,name,age,temp_file=None):self.name=name self.age=age self.temp_file=temp_file# 不打算序列化这个属性def__getstate__(self):# 返回要被序列化的“状态”字典state=self.__dict__.copy()# 删除不希望被序列化的属性if'temp_file'instate:delstate['temp_file']returnstatedef__setstate__(self,state):# 从状态恢复实例self.__dict__.update(state)# 反序列化后,可赋默认值或重新构造资源self.temp_file=None

说明:

  • __getstate__返回任何可被 pickle 序列化的对象(通常是 dict)。
  • __setstate__(state)用来根据序列化得到的state恢复对象内部状态。

3. 更底层的控制:__reduce__/__reduce_ex__

当序列化某个对象时,pickle会调用:

  • obj.__reduce_ex__(protocol)(如存在)
  • 否则调用obj.__reduce__()

它们需要返回一种描述如何重新构造该对象的信息,一般形式是一个 2~5 元组,常见形式:

(callable,args,state)

示例(简单展示用法,不必死记):

classMyClass:def__init__(self,value):self.value=value self.cache=value*2# 想在恢复时重新计算def__reduce__(self):# 用 MyClass 构造函数和一个参数创建实例reconstruct_callable=self.__class__ reconstruct_args=(self.value,)# state 用于存其他信息,这里暂时用 Nonestate=Nonereturn(reconstruct_callable,reconstruct_args,state)def__setstate__(self,state):# 反序列化后,重新构造 cacheself.cache=self.value*2

平时多数情况下只用__getstate__/__setstate__即可,__reduce__适合高级定制或 C 扩展类。


七、处理大型对象与性能优化

1. 使用最高协议 & 二进制 I/O

pickle.dump(obj,f,protocol=pickle.HIGHEST_PROTOCOL)

优点:

  • 通常速度更快
  • 文件更小

2. 使用protocol >= 4的大对象支持

  • 新协议对大对象(>4GB)支持更好。
  • Python 3.8+ 中的默认协议已足够。

3. 对于多对象序列化

若你想把多个对象“顺序写入”同一个文件:

withopen("multi.pkl","wb")asf:pickle.dump(obj1,f,protocol=pickle.HIGHEST_PROTOCOL)pickle.dump(obj2,f,protocol=pickle.HIGHEST_PROTOCOL)withopen("multi.pkl","rb")asf:a=pickle.load(f)b=pickle.load(f)

注意:

  • 加载时需要按相同顺序多次调用pickle.load
  • 不可随机访问中间对象(除非自己管理偏移量)。

如果要实现可随机访问的“对象仓库”,可考虑:

  • shelve模块(基于 pickle + dbm)
  • 或自己实现索引(对象位置表 + seek)

八、安全性:务必注意反序列化风险

这是使用 pickle 时最重要的问题。

1. pickle 反序列化是不安全的

官方文档明确说明:
不可信数据调用pickle.loadpickle.loads危险的,可能导致代码执行、系统被攻陷。

原因:

  • pickle协议中可以编码“调用任意可导入对象”的指令。
  • 恶意构造的 pickle 字节流可以在加载时触发执行任意 Python 代码(RCE)。

总结一句话:

只有在完全信任数据来源的前提下,才能使用pickle.load/pickle.loads

2. 安全使用建议

  • 绝对不要对以下来源的数据使用pickle.loads

    • 用户上传的文件 / 表单
    • 网络请求中的数据(HTTP body / WebSocket 等)
    • 来历不明的.pkl文件
  • 如果必须支持某种持久化格式给外部使用,建议:

    • 使用 JSON、MessagePack、Protocol Buffers、Avro 等更安全和跨语言的序列化格式。
    • 或自行设计清晰受限的数据结构(比如只允许 dict/list/str/int 等基本类型)。
  • 在内部(可信环境)用 pickle:

    • 仅在团队内部、受控环境下使用.pkl共享数据。
    • 若部署在可能暴露接口的服务中,不要直接接受外部传来的 pickled 数据。

九、实际例子:缓存结果到硬盘

示例:耗时计算结果缓存到本地,下次直接读取。

importosimportpickle CACHE_FILE="result_cache.pkl"defheavy_compute():# 模拟耗时操作fromtimeimportsleep sleep(3)return{"result":42,"detail":[1,2,3]}defget_result():ifos.path.exists(CACHE_FILE):withopen(CACHE_FILE,"rb")asf:returnpickle.load(f)res=heavy_compute()withopen(CACHE_FILE,"wb")asf:pickle.dump(res,f,protocol=pickle.HIGHEST_PROTOCOL)returnresif__name__=="__main__":print("First call:")print(get_result())print("Second call (should be faster):")print(get_result())

十、与其它序列化方式的比较(简要)

方式格式可读性跨语言支持复杂 Python 对象安全(默认)典型用途
pickle二进制否(危险)Python 内部的对象持久化
JSON文本限制多(基本类型为主)相对安全简单配置、Web 接口、跨语言
msgpack二进制一般相对安全高效跨语言序列化
protobuf二进制用 schema 定义结构相对安全大规模服务间通信、强类型约束

结论:

  • 只在 Python 内部,且数据来源可信:用pickle很方便,支持自定义类。
  • 需要跨语言或不完全可信数据源:优先考虑 JSON / msgpack / protobuf 等。

十一、小结与使用建议

  1. 基本用法:
    • pickle.dump(obj, f)/pickle.load(f)处理文件;
    • pickle.dumps(obj)/pickle.loads(bytes)处理内存中的 bytes。
  2. 对自定义类:
    • 顶层定义类,反序列化时保持类可导入;
    • 可以用__getstate__/__setstate__精细控制。
  3. 性能:
    • protocol=pickle.HIGHEST_PROTOCOL
    • 注意版本兼容问题。
  4. 安全:
    • 永远不要反序列化不可信来源的 pickle 数据
    • 对外部接口应使用更安全、跨语言的格式。
  5. 场景典型用途:
    • Python 项目内部的模型、缓存、中间结果持久化;
    • 一次性脚本、实验性数据保存。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/29 16:03:37

系统设计能力构建:从技术困境到架构思维的完整路径

系统设计能力构建:从技术困境到架构思维的完整路径 【免费下载链接】system-design Learn how to design systems at scale and prepare for system design interviews 项目地址: https://gitcode.com/GitHub_Trending/sy/system-design 你是否曾面临这样的技…

作者头像 李华
网站建设 2026/4/24 23:43:58

毕设分享 LSTM股价预测

0 简介 今天学长向大家介绍一个机器视觉的毕设项目 毕业设计项目分享 LSTM股价预测 项目运行效果: 毕业设计 lstm股价预测🧿 项目分享:见文末! 1 LSTM 神经网络 长短期记忆 (LSTM) 神经网络属于循环神经网络 (RNN) 的一种,特别适合处理和…

作者头像 李华
网站建设 2026/4/23 13:50:42

桌面共享终极指南:如何实现RTSP/RTMP实时推流

桌面共享终极指南:如何实现RTSP/RTMP实时推流 【免费下载链接】DesktopSharing 桌面共享, 支持RTSP转发, RTSP推流, RTMP推流。 项目地址: https://gitcode.com/gh_mirrors/de/DesktopSharing 想要实现高效的桌面共享和屏幕协作吗?DesktopSharing…

作者头像 李华
网站建设 2026/4/29 21:24:38

GraphQL技术全景解析与全维度攻击面研判

GraphQL是Meta(原Facebook)于2015年开源的数据查询与操作语言及配套运行时环境,其诞生初衷是解决传统REST API在复杂业务场景下的“数据过载”“多端适配难”“接口维护成本高”等痛点。经过近十年的技术迭代,GraphQL已成为前后端…

作者头像 李华
网站建设 2026/4/19 1:24:49

SQL语句***重点

文章目录MySQL执行SQL语句原理SQL分类(CRUD)DDL语句CREATE--创建ALTER--修改DROP--删除DCL语句GRANT---授权REVOKE--删除权限COMMIT--永久数据修改DML语句insert--插入数据update--更新数据delete--删除数据truncate--永久删除数据delete truncate drop删…

作者头像 李华
网站建设 2026/4/29 1:31:49

揭秘企业级Agent部署难题:如何通过Docker实现零信任安全架构?

第一章:企业级Agent的Docker安全配置在企业级应用中,Agent通常以Docker容器形式部署,承担监控、日志收集或自动化运维等关键任务。确保其运行环境的安全性至关重要。合理的Docker安全配置不仅能防止未授权访问,还能降低容器逃逸、…

作者头像 李华