news 2026/4/20 21:27:35

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/18 3:43:54

性能优化关键策略:Ascend C Tiling(分块)机制原理解析

目录 摘要 1 引言:为什么Tiling是性能优化的核心? 1.1 硬件瓶颈的本质 1.2 Tiling的技术价值 2 Tiling技术原理深度解析 2.1 硬件架构与Tiling的数学基础 2.1.1 Tiling问题的形式化定义 2.1.2 多核负载均衡算法 2.2 Tiling策略分类与适用场景 …

作者头像 李华
网站建设 2026/4/17 7:38:06

如何用AI工具3步制作专业解说视频?零基础也能轻松上手

如何用AI工具3步制作专业解说视频?零基础也能轻松上手 【免费下载链接】NarratoAI 利用AI大模型,一键解说并剪辑视频; Using AI models to automatically provide commentary and edit videos with a single click. 项目地址: https://gitc…

作者头像 李华
网站建设 2026/4/20 17:15:56

milvus向量数据库使用尝试

一.背景在大语言模型(LLM)、计算机视觉、推荐系统等人工智能应用落地过程中,非结构化数据(文本、图片、音频、视频)的相似性检索成为核心需求 —— 这类数据需先通过模型转化为高维向量,再通过向量相似性计…

作者头像 李华
网站建设 2026/4/18 5:31:07

EasyGBS:一体化视频监控与智能管理解决方案

在数字化转型加速推进的背景下,视频监控已成为各行业安全管理、应急处置、运营优化的核心支撑手段。国标GB28181算法算力平台EasyGBS,凭借全协议兼容接入、全流程协同调度等核心能力,构建了一体化视频监控解决方案,广泛适配多样化…

作者头像 李华
网站建设 2026/4/18 5:31:33

为什么顶尖团队都在用MCP PL-600设计多模态Agent?真相令人震惊

第一章:MCP PL-600与多模态Agent的革命性融合MCP PL-600作为新一代高性能控制处理器,凭借其强大的并行计算能力与低延迟通信架构,正成为多模态智能体(Multimodal Agent)系统的核心驱动引擎。该处理器集成了专用AI加速单…

作者头像 李华
网站建设 2026/4/18 5:31:33

为什么你的量子模拟总卡顿?:深入VSCode性能分析底层机制

第一章:为什么你的量子模拟总卡顿?量子模拟在现代科研与算法开发中扮演着关键角色,但许多开发者发现其运行效率远低于预期。性能瓶颈往往并非来自算法设计本身,而是底层资源管理与模拟器配置的不合理。硬件资源分配不足 量子态的指…

作者头像 李华