pickle,一个方便的 Python 库!
【pickle,一个方便的 Python 库!】
在日常生活与工作中,我们经常需要将程序运行过程中的数据“记住”——比如你写了一个待办事项应用,用户添加了几条任务,关闭程序后下次打开还想看到这些任务;或者你正在训练一个机器学习模型,跑了几个小时,突然断电,所有中间结果丢失;又或者你在玩一个文字冒险游戏,角色升到了10级,退出后希望下次能继续。这些场景本质上都是数据持久化问题:如何把内存中的 Python 对象(列表、字典、自定义类实例等)保存到磁盘文件,并在需要时完美地恢复回来。
Python 内置的 pickle 库正是为此而生。它实现了对 Python 对象结构的序列化(Serialization)与反序列化(Deserialization)。序列化将对象转换为字节流,可以写入文件或通过网络传输;反序列化则从字节流中重建原始对象。pickle 的强大之处在于它几乎支持所有 Python 内置类型,甚至包括嵌套对象、循环引用和自定义类的实例。相比 JSON 只能处理基本类型,pickle 能“原汁原味”地保存 Python 对象的状态,包括函数、类、甚至闭包。
日常生活中,pickle 的应用悄然存在:游戏存档、IDE 的配置记忆、数据科学中的中间结果缓存、Web 应用的 Session 存储(部分框架)…… 有了它,你的程序就具备了“记忆”能力。
安装库
pickle 是 Python 标准库的一部分,无需额外安装,直接导入即可:
python
import pickle
如果你使用的是 PyPy 或其他兼容环境,pickle 同样可用。需要留意的是,不同 Python 版本间的 pickle 协议可能有细微差异,但向下兼容做得很好。
基本用法
我们将通过 4 个步骤掌握 pickle 的核心操作。
1. 将对象序列化到文件(dump)
python
import pickle
data = {
'name': 'Alice',
'scores': [98, 87, 92],
'completed': True
}
with open('data.pkl', 'wb') as f:
pickle.dump(data, f)
dump(obj, file) 要求文件以二进制写模式 'wb' 打开。上述代码将字典对象保存到 data.pkl 文件中。
2. 从文件反序列化对象(load)
python
with open('data.pkl', 'rb') as f:
loaded_data = pickle.load(f)
print(loaded_data)
# 输出:{'name': 'Alice', 'scores': [98, 87, 92], 'completed': True}
load(file) 从二进制文件中读取字节流并重建对象。注意文件路径和权限。
3. 序列化为字节对象(dumps)
如果不想写入文件,而是直接在内存中得到字节串(例如用于网络传输或存入数据库 BLOB 字段),可以使用 dumps:
python
bytes_data = pickle.dumps([1, 2, 3]) print(bytes_data) # b'\x80\x04\x95\x0f\x00\x00\x00\x00\x00\x00\x00]\x94(K\x01K\x02K\x03e.'
4. 从字节对象反序列化(loads)
python
restored_list = pickle.loads(bytes_data) print(restored_list) # [1, 2, 3]
高级用法
协议版本选择
pickle 提供了 5 种协议版本(0~4,Python 3.8+ 有协议 5)。默认使用 DEFAULT_PROTOCOL(通常是最高支持版本)。为了兼容性,可以显式指定:
python
pickle.dump(data, f, protocol=4) # 协议4支持大对象
自定义类的序列化控制
对于自定义类,pickle 默认会保存实例的 __dict__ 属性。如果需要精细控制,可以定义 __getstate__ 和 __setstate__ 方法:
python
class Player:
def __init__(self, name, level, password):
self.name = name
self.level = level
self.password = password # 不想序列化敏感信息
def __getstate__(self):
state = self.__dict__.copy()
del state['password'] # 排除密码字段
return state
def __setstate__(self, state):
self.__dict__.update(state)
self.password = None # 反序列化后重置为默认值
处理不可信数据 —— 安全警告
重要:不要对来自不可信来源(网络、用户上传、未知文件)的数据使用 pickle.load()。因为 pickle 在反序列化过程中可以执行任意代码,存在严重安全风险。如果需要安全的数据交换,请考虑 json 或自定义解析器。
实际应用场景(附深度案例代码)
场景一:游戏进度保存与恢复
许多单机游戏使用 pickle 保存玩家状态。以下是一个简单的 RPG 角色存档示例:
python
import pickle
import os
class GameState:
def __init__(self, level=1, hp=100, inventory=None):
self.level = level
self.hp = hp
self.inventory = inventory if inventory else []
def save(self, filename="savegame.dat"):
with open(filename, "wb") as f:
pickle.dump(self, f)
print("游戏已保存")
@staticmethod
def load(filename="savegame.dat"):
if not os.path.exists(filename):
return GameState()
with open(filename, "rb") as f:
return pickle.load(f)
# 使用示例
state = GameState.load()
print(f"当前等级: {state.level}, 血量: {state.hp}")
# 玩家升级
state.level = 5
state.hp = 200
state.inventory.append("魔法剑")
state.save()
# 下次启动
new_state = GameState.load()
print(f"读取成功: 等级 {new_state.level}, 物品 {new_state.inventory}")
场景二:机器学习模型的暂存
数据科学家训练模型动辄数小时,使用 pickle 可以保存中间状态,避免重复计算。
python
from sklearn.ensemble import RandomForestClassifier
import pickle
# 模拟训练一个复杂模型
X = [[0,0], [1,1], [2,2], [3,3]]
y = [0,1,1,0]
model = RandomForestClassifier(n_estimators=100)
model.fit(X, y)
# 保存模型到文件
with open('model.pkl', 'wb') as f:
pickle.dump(model, f)
# 在另一处加载并预测
with open('model.pkl', 'rb') as f:
loaded_model = pickle.load(f)
print(loaded_model.predict([[1.5, 1.5]])) # 输出预测结果
场景三:爬虫断点续爬
长时间爬取网页时,可以用 pickle 保存已抓取的 URL 队列和已处理的数量。
python
import pickle
import os
CRAWL_STATE_FILE = "crawl_state.pkl"
def save_state(visited, queue):
with open(CRAWL_STATE_FILE, "wb") as f:
pickle.dump((visited, queue), f)
def load_state():
if not os.path.exists(CRAWL_STATE_FILE):
return set(), []
with open(CRAWL_STATE_FILE, "rb") as f:
return pickle.load(f)
# 模拟爬虫主循环
visited_urls, url_queue = load_state()
if not url_queue:
url_queue = ["https://example.com/start"]
while url_queue:
url = url_queue.pop()
if url in visited_urls:
continue
# 模拟抓取
print(f"Crawling {url}")
visited_urls.add(url)
# 发现新链接
new_links = ["https://example.com/page1", "https://example.com/page2"]
url_queue.extend(new_links)
# 每抓取10个保存一次状态
if len(visited_urls) % 10 == 0:
save_state(visited_urls, url_queue)
print("进度已保存,可中断后继续")
总结与互动
pickle 是 Python 生态中一把锋利且实用的瑞士军刀,它以极简的 API 解决了对象持久化的核心痛点。从游戏存档到模型训练,从配置记忆到爬虫断点,你都能看到它的身影。但请牢记:永远不要反序列化不信任的数据,这是使用 pickle 的安全红线。
你在日常项目中是否也遇到过需要“把 Python 对象存下来”的瞬间?是用 JSON、SQLite 还是直接手写格式解析?不妨尝试用 pickle 重构一下,体会那种“一键保存整个宇宙”的畅快感。如果有什么独特的应用点子,欢迎在评论区分享,让我们一起挖掘这个低调库的更多可能!
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)