文章目录
- pickle.dump(obj, file, protocol=None):将对象obj序列化后写入文件对象file(需以二进制模式打开)。 pickle.dumps(obj, protocol=None):将对象obj序列化为字节流(bytes类型),返回该字节流。 示例:序列化基本对象 import pickle # 定义一个复杂对象(包含多种类型) data = { “name”: “Alice”, “age”: 30, “hobbies”: [“reading”, “hiking”], “is_student”: False, “scores”: (90.5, 85.0) } # 方法1:用dumps()序列化为字节流 data_bytes = pickle.dumps(data) print(“序列化结果(字节流):”, data_bytes) # 输出b’x80x04…’(二进制数据) # 方法2:用dump()序列化到文件 with open(“data.pkl”, “wb”) as f: # 必须用二进制模式”wb” pickle.dump(data, f)
- pickle.load(file):从文件对象file(二进制模式打开)中读取字节流,反序列化为 Python 对象并返回。 pickle.loads(bytes_obj):将字节流bytes_obj反序列化为 Python 对象并返回。 示例:反序列化恢复对象 import pickle # 方法1:用loads()从字节流反序列化 data_bytes = pickle.dumps({“name”: “Alice”}) restored_data = pickle.loads(data_bytes) print(“从字节流恢复:”, restored_data) # 输出 {‘name’: ‘Alice’} # 方法2:用load()从文件反序列化 with open(“data.pkl”, “rb”) as f: # 必须用二进制模式”rb” restored_from_file = pickle.load(f) print(“从文件恢复:”, restored_from_file) # 输出原始data字典
- import pickle class Person: def __init__(self, name, age): self.name = name self.age = age def greet(self): return f”Hello, I’m {self.name}!” # 创建实例 person = Person(“Bob”, 25) # 序列化 person_bytes = pickle.dumps(person) # 反序列化(需确保Person类在当前作用域中) restored_person = pickle.loads(person_bytes) print(restored_person.greet()) # 输出 “Hello, I’m Bob!” print(restored_person.age) # 输出 25
- 默认情况下,pickle会序列化对象的__dict__(实例属性字典),但你可以通过以下方法自定义序列化内容: __getstate__():返回需要序列化的数据(如字典),替代默认的__dict__; __setstate__(state):接收反序列化后的数据state,用于恢复对象状态。 示例:过滤敏感信息 import pickle class User: def __init__(self, username, password): self.username = username self.password = password # 敏感信息,不希望被序列化 # 自定义序列化内容:只保留username def __getstate__(self): return {“username”: self.username} # 自定义反序列化逻辑:恢复状态 def __setstate__(self, state): self.username = state[“username”] self.password = “default” # 反序列化时密码设为默认值 # 创建实例 user = User(“alice123”, “secret123”) # 序列化 user_bytes = pickle.dumps(user) # 反序列化 restored_user = pickle.loads(user_bytes) print(restored_user.username) # 输出 “alice123” print(restored_user.password) # 输出 “default”(敏感信息未被序列化)
- pickle反序列化时会执行字节流中包含的代码,若从不可信来源(如网络、未知文件)加载数据,可能导致恶意代码执行(如删除文件、窃取信息)。 禁止反序列化未知来源的数据,若需网络传输,建议使用更安全的格式(如 JSON,仅支持基础类型)。
- 类定义变化:若反序列化时的类定义与序列化时不同(如新增 / 删除属性、修改类名),可能导致反序列化失败; 跨版本兼容性:高版本协议(如 4)序列化的数据无法在低版本 Python(如 3.3 以下)中反序列化; 模块路径变化:若类所在的模块路径改变(如从moduleA移到moduleB),反序列化时需确保能正确导入类。
- 部分 Python 对象无法被序列化,例如: 生成器、lambda 函数(匿名函数); 线程、进程、文件对象等与系统资源相关的对象; 某些内置模块的对象(如sys.stdin)。 序列化这些对象会抛出PickleError。
- 将程序运行中的关键对象(如配置、中间结果)保存到文件,下次运行时直接恢复,避免重复计算。 import pickle import time def expensive_computation(): # 模拟耗时计算 time.sleep(3) return [i**2 for i in range(1000)] # 检查是否有缓存 try: with open(“result_cache.pkl”, “rb”) as f: result = pickle.load(f) print(“从缓存加载结果”) except FileNotFoundError: # 无缓存则计算并保存 result = expensive_computation() with open(“result_cache.pkl”, “wb”) as f: pickle.dump(result, f) print(“计算完成并缓存”)
- 在多进程编程中,pickle是进程间传递复杂对象的默认方式(如multiprocessing模块依赖pickle序列化数据)。 from multiprocessing import Process import pickle def process_data(data): print(“子进程接收数据:”, data) if __name__ == “__main__”: # 定义复杂对象 data = {“task”: “process”, “params”: [1, 2, 3]} # 多进程会自动序列化data并传递给子进程 p = Process(target=process_data, args=(data,)) p.start() p.join()
目录
- 一、核心概念:序列化与反序列化
- 二、基本用法:pickle 的核心函数
- 1. 序列化:dump()与dumps()
- 2. 反序列化:load()与loads()
- 三、高级特性:自定义类的序列化
- 1. 基本自定义类序列化
- 2. 自定义序列化逻辑(__getstate__与__setstate__)
- 四、协议版本:影响序列化效率与兼容性
- 五、注意事项:安全与兼容性问题
- 1. 安全性风险:反序列化不可信数据
- 2. 兼容性问题
- 3. 不支持的类型
- 六、实战场景:对象持久化与数据缓存
- 1. 保存程序状态(持久化)
- 2. 跨进程数据传递
- 七、与 JSON 的对比:何时用 pickle?
- 总结
在 Python 中,pickle模块是实现对象序列化与反序列化的核心工具,它能将 Python 对象(如列表、字典、类实例等)转换为字节流以便存储或传输,也能将字节流恢复为原始对象。本文将系统讲解pickle模块的工作原理、基本用法、高级特性及注意事项,帮助你在实际开发中灵活运用对象持久化技术。
- 序列化(pickling):将 Python 对象转换为字节流(二进制数据)的过程,便于存储到文件或通过网络传输。
- 反序列化(unpickling):将字节流恢复为 Python 对象的过程,从文件或网络数据中重建原始对象。
pickle模块支持几乎所有 Python 内置对象的序列化,包括:
- 基本数据类型(int、float、str、bool、None);
- 容器类型(list、tuple、dict、set);
- 自定义类实例、函数、类(需注意特殊处理)。
pickle模块的核心功能通过四个函数实现:dump()、dumps()、load()、loads(),区分在于是否直接操作文件对象。
pickle.dump(obj, file, protocol=None):将对象obj序列化后写入文件对象file(需以二进制模式打开)。
pickle.dumps(obj, protocol=None):将对象obj序列化为字节流(bytes类型),返回该字节流。
pickle.dump(obj, file, protocol=None):将对象obj序列化后写入文件对象file(需以二进制模式打开)。pickle.dumps(obj, protocol=None):将对象obj序列化为字节流(bytes类型),返回该字节流。示例:序列化基本对象
import pickle
# 定义一个复杂对象(包含多种类型)
data = {
"name": "Alice",
"age": 30,
"hobbies": ["reading", "hiking"],
"is_student": False,
"scores": (90.5, 85.0)
}
# 方法1:用dumps()序列化为字节流
data_bytes = pickle.dumps(data)
print("序列化结果(字节流):", data_bytes) # 输出b'x80x04...'(二进制数据)
# 方法2:用dump()序列化到文件
with open("data.pkl", "wb") as f: # 必须用二进制模式"wb"
pickle.dump(data, f)
pickle.load(file):从文件对象file(二进制模式打开)中读取字节流,反序列化为 Python 对象并返回。
pickle.loads(bytes_obj):将字节流bytes_obj反序列化为 Python 对象并返回。
pickle.load(file):从文件对象file(二进制模式打开)中读取字节流,反序列化为 Python 对象并返回。pickle.loads(bytes_obj):将字节流bytes_obj反序列化为 Python 对象并返回。示例:反序列化恢复对象
import pickle
# 方法1:用loads()从字节流反序列化
data_bytes = pickle.dumps({"name": "Alice"})
restored_data = pickle.loads(data_bytes)
print("从字节流恢复:", restored_data) # 输出 {'name': 'Alice'}
# 方法2:用load()从文件反序列化
with open("data.pkl", "rb") as f: # 必须用二进制模式"rb"
restored_from_file = pickle.load(f)
print("从文件恢复:", restored_from_file) # 输出原始data字典
pickle不仅支持内置对象,还能序列化自定义类的实例,但需要注意类定义的可访问性(反序列化时需能导入原类)。
import pickle
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return f"Hello, I'm {self.name}!"
# 创建实例
person = Person("Bob", 25)
# 序列化
person_bytes = pickle.dumps(person)
# 反序列化(需确保Person类在当前作用域中)
restored_person = pickle.loads(person_bytes)
print(restored_person.greet()) # 输出 "Hello, I'm Bob!"
print(restored_person.age) # 输出 25
默认情况下,pickle会序列化对象的__dict__(实例属性字典),但你可以通过以下方法自定义序列化内容:
__getstate__():返回需要序列化的数据(如字典),替代默认的__dict__;__setstate__(state):接收反序列化后的数据state,用于恢复对象状态。
示例:过滤敏感信息
import pickle
class User:
def __init__(self, username, password):
self.username = username
self.password = password # 敏感信息,不希望被序列化
# 自定义序列化内容:只保留username
def __getstate__(self):
return {"username": self.username}
# 自定义反序列化逻辑:恢复状态
def __setstate__(self, state):
self.username = state["username"]
self.password = "default" # 反序列化时密码设为默认值
# 创建实例
user = User("alice123", "secret123")
# 序列化
user_bytes = pickle.dumps(user)
# 反序列化
restored_user = pickle.loads(user_bytes)
print(restored_user.username) # 输出 "alice123"
print(restored_user.password) # 输出 "default"(敏感信息未被序列化)
pickle支持多种序列化协议(版本),不同版本在效率、兼容性上有差异:
- 协议 0:文本格式,兼容旧版本 Python(默认在 Python 2 中),效率低;
- 协议 1:二进制格式,兼容 Python 2 和 3;
- 协议 2:Python 2.3 + 引入,支持新特性(如新式类);
- 协议 3:Python 3.0 + 引入,不兼容 Python 2;
- 协议 4:Python 3.4 + 引入,支持更大对象、更多类型(如
bytes、set等),是 Python 3.8 + 的默认协议。
指定协议版本:通过protocol参数设置(如protocol=4),值越高通常效率越好(但兼容性可能降低)。
import pickle data = [i for i in range(1000)] # 使用协议4序列化(效率更高) data_bytes = pickle.dumps(data, protocol=4)
pickle反序列化时会执行字节流中包含的代码,若从不可信来源(如网络、未知文件)加载数据,可能导致恶意代码执行(如删除文件、窃取信息)。
禁止反序列化未知来源的数据,若需网络传输,建议使用更安全的格式(如 JSON,仅支持基础类型)。
- 类定义变化:若反序列化时的类定义与序列化时不同(如新增 / 删除属性、修改类名),可能导致反序列化失败;
- 跨版本兼容性:高版本协议(如 4)序列化的数据无法在低版本 Python(如 3.3 以下)中反序列化;
- 模块路径变化:若类所在的模块路径改变(如从
moduleA移到moduleB),反序列化时需确保能正确导入类。
moduleA移到moduleB),反序列化时需确保能正确导入类。
部分 Python 对象无法被序列化,例如:
- 生成器、lambda 函数(匿名函数);
- 线程、进程、文件对象等与系统资源相关的对象;
- 某些内置模块的对象(如
sys.stdin)。
序列化这些对象会抛出PickleError。
将程序运行中的关键对象(如配置、中间结果)保存到文件,下次运行时直接恢复,避免重复计算。
import pickle
import time
def expensive_computation():
# 模拟耗时计算
time.sleep(3)
return [i**2 for i in range(1000)]
# 检查是否有缓存
try:
with open("result_cache.pkl", "rb") as f:
result = pickle.load(f)
print("从缓存加载结果")
except FileNotFoundError:
# 无缓存则计算并保存
result = expensive_computation()
with open("result_cache.pkl", "wb") as f:
pickle.dump(result, f)
print("计算完成并缓存")
在多进程编程中,pickle是进程间传递复杂对象的默认方式(如multiprocessing模块依赖pickle序列化数据)。
from multiprocessing import Process
import pickle
def process_data(data):
print("子进程接收数据:", data)
if __name__ == "__main__":
# 定义复杂对象
data = {"task": "process", "params": [1, 2, 3]}
# 多进程会自动序列化data并传递给子进程
p = Process(target=process_data, args=(data,))
p.start()
p.join()
| 特性 | pickle | JSON |
|---|---|---|
| 支持类型 | 几乎所有 Python 对象(类实例、函数等) | 仅基础类型(str、int、list、dict 等) |
| 数据格式 | 二进制(不可读) | 文本(人类可读) |
| 安全性 | 不安全(可能执行恶意代码) | 安全(纯数据解析) |
| 跨语言支持 | 仅 Python | 所有主流语言支持 |
| 用途 | Python 内部对象持久化、进程间通信 | 跨语言数据交换、配置文件 |
选择建议:
- 仅在 Python 生态内使用,且需要序列化复杂对象(如类实例)→ 用
pickle; - 需跨语言交互,或数据需人类可读、可编辑 → 用 JSON。
pickle模块是 Python 对象序列化的核心工具,通过dump()/dumps()和load()/loads()实现对象与字节流的转换,支持自定义类实例及复杂数据结构。但需注意其安全性风险(禁止处理不可信数据)和兼容性限制。
在实际开发中,pickle适用于 Python 内部的对象持久化、进程间通信等场景,是提升程序效率和灵活性的重要手段。合理使用pickle,可简化复杂数据的存储与传输逻辑。
到此这篇关于Python3 Pickle 模块详解的文章就介绍到这了,更多相关python pickle 模块内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- Python pickle模块的使用指南
- Python pickle模块进行序列化的实现示例
- Python中的pickle模块常用函数
- Python中pickle模块的使用详解
- 浅谈Python使用pickle模块序列化数据优化代码的方法
- Python数据序列化之pickle模块
- python中pickle模块浅析
- 详解Python3 pickle模块用法
- Python使用pickle模块储存对象操作示例
- Python pickle模块用法实例