2026抚州市权威认证贵金属回收 TOP5+黄金回收白银回收铂金回收门店地址电话推荐
2026/6/12 10:02:53
pickle是 Python 标准库中的对象序列化工具:
特点:
适用场景:在 Python 环境内部保存/恢复复杂对象(如机器学习模型、缓存的中间结果、复杂数据结构等)。
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(推荐)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"。importpickle obj=[1,2,3,{"a":10}]data_bytes=pickle.dumps(obj,protocol=pickle.HIGHEST_PROTOCOL)# 可以用于网络传输、缓存等restored=pickle.loads(data_bytes)print(restored)大多数常见类型都支持:
int、float、bool、str、bytes、Nonelist、tuple、dict、set、frozensetdatetime、decimal.Decimal、fractions.Fraction等常用内置类型sklearn模型)——库作者实现了对应的序列化协议不太适合 / 有限制的对象:
pickle不能可靠处理(要用dill等扩展库)protocol是决定如何编码对象为字节流的“格式版本”。
pickle.dump(obj,f,protocol=pickle.HIGHEST_PROTOCOL)importpickleprint(pickle.HIGHEST_PROTOCOL)跨 Python 版本使用 Pickle 时:
.pkl文件,建议:HIGHEST_PROTOCOL,然后在较高版本中固定使用该协议版本。默认情况下,自定义类的实例是可以被 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。__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恢复对象内部状态。__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 扩展类。
pickle.dump(obj,f,protocol=pickle.HIGHEST_PROTOCOL)优点:
protocol >= 4的大对象支持若你想把多个对象“顺序写入”同一个文件:
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)这是使用 pickle 时最重要的问题。
官方文档明确说明:
对不可信数据调用pickle.load或pickle.loads是危险的,可能导致代码执行、系统被攻陷。
原因:
pickle协议中可以编码“调用任意可导入对象”的指令。总结一句话:
只有在完全信任数据来源的前提下,才能使用
pickle.load/pickle.loads。
绝对不要对以下来源的数据使用pickle.loads:
.pkl文件如果必须支持某种持久化格式给外部使用,建议:
在内部(可信环境)用 pickle:
.pkl共享数据。示例:耗时计算结果缓存到本地,下次直接读取。
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 定义结构 | 相对安全 | 大规模服务间通信、强类型约束 |
结论:
pickle很方便,支持自定义类。pickle.dump(obj, f)/pickle.load(f)处理文件;pickle.dumps(obj)/pickle.loads(bytes)处理内存中的 bytes。__getstate__/__setstate__精细控制。protocol=pickle.HIGHEST_PROTOCOL;