张芷铭的个人博客

序列化:对象 → 字节流

在 Python 中,序列化(Serialization)是将对象转换为可存储或传输的格式(如字节流、字符串),反序列化(Deserialization)则是将序列化后的数据还原为原始对象的过程。以下是常见的序列化和反序列化方法:


1. 使用 pickle 模块(Python 原生)

特点:支持几乎所有 Python 对象(包括自定义类),但仅限 Python 使用,不安全(反序列化可能执行任意代码)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import pickle

# 序列化:对象 → 字节流
data = {"name": "Alice", "age": 30}
serialized = pickle.dumps(data)  # 返回 bytes

# 保存到文件
with open("data.pkl", "wb") as f:
    pickle.dump(data, f)

# 反序列化:字节流 → 对象
deserialized = pickle.loads(serialized)  # 返回原始对象

# 从文件加载
with open("data.pkl", "rb") as f:
    loaded_data = pickle.load(f)

2. 使用 json 模块(跨语言)

特点:跨语言兼容(JSON 格式),但仅支持基础数据类型(字典、列表、字符串、数字等)。自定义对象需额外处理。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
import json

# 序列化:对象 → JSON 字符串
data = {"name": "Bob", "scores": [90, 85]}
json_str = json.dumps(data)  # 返回字符串

# 保存到文件
with open("data.json", "w") as f:
    json.dump(data, f)

# 反序列化:JSON 字符串 → 对象
obj = json.loads(json_str)  # 返回字典

# 从文件加载
with open("data.json", "r") as f:
    loaded_data = json.load(f)

处理自定义对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# 序列化自定义对象(需定义转换函数)
class User:
    def __init__(self, name, age):
        self.name = name
        self.age = age

def encode_user(obj):
    if isinstance(obj, User):
        return {"name": obj.name, "age": obj.age}  # 转为字典
    raise TypeError("Object not serializable")

user = User("Charlie", 25)
user_json = json.dumps(user, default=encode_user)

# 反序列化自定义对象
def decode_user(dct):
    if "name" in dct and "age" in dct:
        return User(dct["name"], dct["age"])
    return dct

user_obj = json.loads(user_json, object_hook=decode_user)

3. 使用 marshal 模块(不推荐)

特点:Python 内部格式,用于 .pyc 文件。不推荐用于通用序列化(格式不稳定,文档明确警告)。


4. 第三方库

(1) yaml(YAML 格式)

1
2
3
4
5
6
7
8
import yaml  # 需安装 pyyaml

# 序列化
data = {"key": "value"}
yaml_str = yaml.dump(data)

# 反序列化
obj = yaml.safe_load(yaml_str)  # 安全加载避免代码执行

(2) msgpack(高效二进制)

1
2
3
4
5
6
7
8
import msgpack  # 需安装 msgpack

# 序列化
data = {"id": 1, "tags": ["a", "b"]}
packed = msgpack.packb(data)

# 反序列化
unpacked = msgpack.unpackb(packed)

(3) pydantic + json(带验证的序列化)

适用于数据模型验证和序列化:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float

# 对象 → JSON
item = Item(name="Book", price=9.99)
json_str = item.json()  # '{"name": "Book", "price": 9.99}'

# JSON → 对象
new_item = Item.parse_raw(json_str)

关键注意事项

  1. 安全性
    • pickle 反序列化可能执行恶意代码,切勿加载不受信任的数据
    • 优先使用 jsonyaml.safe_load 处理外部数据。
  2. 自定义对象
    • pickle 自动处理自定义类(需类定义在作用域内)。
    • json 需手动实现转换逻辑(如 defaultobject_hook)。
  3. 性能
    • 二进制格式(如 picklemsgpack)通常比文本格式(如 json)更快更紧凑。

总结

场景推荐工具
Python 内部对象持久化pickle
跨语言/Web API 数据交换json
配置文件读写yaml
高性能二进制传输msgpack
数据模型验证 + 序列化pydantic + json

根据需求选择合适的方法,优先考虑安全性和兼容性!

💬 评论