当前位置:首页>python>Python 对象的序列化与反序列化

Python 对象的序列化与反序列化

  • 2026-08-23 03:00:59
Python 对象的序列化与反序列化

基本用法

序列化是将对象的状态信息转换为可以存储或传输的形式的过程。反序列化则是将这种形式的数据恢复为原始对象的过程。在Python中,执行对象序列号的标准库模块是pickle。pickle协议可以将几乎所有的Python对象转换为字节流。主要用于:

  • 保存模型、配置、状态
  • 进程间通信(IPC):同Python环境传输对象

简单示例:

import pickle

# ======================
# 1. 基础对象序列化/反序列化
# ======================
data = {
"name": "test_user",
"age": 25,
"scores": [90, 88, 95],
"is_student": True
}

# dumps → 转字节流;loads → 从字节流恢复
pickle_bytes = pickle.dumps(data, protocol=pickle.HIGHEST_PROTOCOL)
restored_data = pickle.loads(pickle_bytes)

print("=== 基础对象恢复 ===")
print(restored_data)

# ======================
# 2. 写入/读取文件
# ======================
with open("data.pkl", "wb") as f:
# 写入文件,使用最高协议
    pickle.dump(data, f, protocol=pickle.HIGHEST_PROTOCOL)

with open("data.pkl", "rb") as f:
    loaded_from_file = pickle.load(f)

print("\n=== 从文件恢复 ===")
print(loaded_from_file)

# ======================
# 3. 自定义类实例序列化
# ======================
classStudent:
def__init__(self, name, score):
        self.name = name
        self.score = score

def__repr__(self):
returnf"Student(name={self.name!r}, score={self.score})"

# 创建实例
stu = Student("Tom", 92)
stu_bytes = pickle.dumps(stu)
restored_stu = pickle.loads(stu_bytes)

print("\n=== 自定义类恢复 ===")
print(restored_stu)

# ======================
# 4. 查看协议版本
# ======================
print("\n=== 协议版本 ===")
print(f"当前最高协议: {pickle.HIGHEST_PROTOCOL}")

# === 基础对象恢复 ===
# {'name': 'test_user', 'age': 25, 'scores': [90, 88, 95], 'is_student': True}  
# # === 从文件恢复 ===
# {'name': 'test_user', 'age': 25, 'scores': [90, 88, 95], 'is_student': True}  
# # === 自定义类恢复 ===
# Student(name='Tom', score=92)  
# # === 协议版本 ===
# 当前最高协议: 4

pickle的四种方式

函数
作用
pickle.dumps(obj)
序列化 → 返回 bytes(内存)
pickle.loads(data)
反序列化 ← bytes
pickle.dump(obj, f)
序列化 → 写入文件
pickle.load(f)
反序列化 ← 读取文件

写入文件通常会用于什么时候呢?比如我希望一个状态缓存需要多次运行间进行保持,如果用前面存入内存的话,在程序结束->内存释放->状态就会丢失

注:写入文件,存什么扩展名都可以(.pkl,.cache等)

不安全的点

序列化一个对象时,pickle 不是只存数据,而是存「一套 “重建这个对象” 的指令」。所以攻击者可以手工伪造一段pickle字节流,假如里面的指令不是“重建对象”,而是偷文件、开后门就很危险了。

import pickle  

classStealFile:
def__reduce__(self):
return (print, (open("test.txt", "r", encoding="utf-8").read(),))  

# 先创建一个测试文件(自动用UTF-8)  
with open("test.txt", "w", encoding="utf-8") as f:  
    f.write("这是秘密文件内容:账号密码 123456")  

# 构造恶意 
picklemalicious_pkl = pickle.dumps(StealFile())  

# 加载恶意 pickle → 自动读取文件!  
print("开始加载恶意 pickle...")  
pickle.loads(malicious_pkl)

为什么 pickle 能做到这一点?

因为 pickle 反序列化时:

  1. 会「递归执行对象里的 __reduce__ 方法」
  2. __reduce__ 可以返回「任意函数 + 任意参数」

所以,pickle 只能用于:自己序列化、自己加载

最新文章

随机文章