序列化
本教程共 70 篇 · 第 47 篇 · 更新于 2026-07-22 · 约 6 分钟阅读
47. 序列化
本节目标:掌握
pickle、json和csv三种数据持久化方式,理解各自的适用场景和安全性差异。
内存里的数据结构(列表、字典、对象)程序一关就消失。把它们转成可以存储或传输的格式,这个过程叫「序列化(serialization)」。反方向从存储格式恢复数据结构,叫「反序列化(deserialization)」。
Python 提供了多种序列化工具。这一章讲最常用的三种:pickle、json 和 csv。
pickle:Python 对象的专用序列化
pickle 模块可以把几乎任何 Python 对象转成字节流,也能完全恢复:
import pickle
data = {'name': 'Alice', 'age': 25, 'scores': [85, 90, 88]}
# 序列化到文件
with open('data.pkl', 'wb') as f:
pickle.dump(data, f)
# 从文件反序列化
with open('data.pkl', 'rb') as f:
loaded = pickle.load(f)
print(loaded) # {'name': 'Alice', 'age': 25, 'scores': [85, 90, 88]}
dump 和 load 操作文件对象,dumps 和 loads 操作内存中的 bytes:
import pickle
blob = pickle.dumps(data)
print(type(blob)) # <class 'bytes'>
loaded = pickle.loads(blob)
print(loaded == data) # True
Warning
pickle绝对不要加载不可信来源的数据。恶意构造的 pickle 数据可以在反序列化时执行任意代码。只用来处理自己生成的文件,或者完全可信的内部数据交换。
JSON:跨语言的通用格式
JSON(JavaScript Object Notation)是 web 开发的事实标准。Python 的 json 模块支持它:
import json
data = {'name': 'Alice', 'age': 25, 'active': True}
# 序列化为 JSON 字符串
json_str = json.dumps(data, ensure_ascii=False)
print(json_str) # {"name": "Alice", "age": 25, "active": true}
# 反序列化
loaded = json.loads(json_str)
print(loaded) # {'name': 'Alice', 'age': 25, 'active': True}
ensure_ascii=False 让中文字符原样输出,否则会被转义成 \uXXXX。
读写 JSON 文件
# 写入
with open('config.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
# 读取
with open('config.json', 'r', encoding='utf-8') as f:
config = json.load(f)
indent=2 让输出带缩进,方便人类阅读。
JSON 不支持的数据类型
JSON 的类型系统比 Python 严格。以下类型不能直接序列化:
datetime→ 手动转成字符串set→ 先转成list- 自定义类的实例 → 需要自定义编码器
from datetime import datetime
import json
class User:
def __init__(self, name, created_at):
self.name = name
self.created_at = created_at
u = User('Bob', datetime.now())
# 自定义编码函数
def encode_user(obj):
if isinstance(obj, User):
return {
'__type__': 'User',
'name': obj.name,
'created_at': obj.created_at.isoformat()
}
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"无法序列化 {type(obj)}")
json_str = json.dumps(u, default=encode_user, ensure_ascii=False)
print(json_str)
default 参数接收一个函数,遇到无法序列化的对象时调用。反序列化时,配合 object_hook 恢复成原始对象。
Note如果项目里频繁遇到「自定义类与 JSON 互转」,考虑用
dataclasses配合第三方库dataclasses-json,能省很多手写转换代码。
csv:表格数据的轻量格式
CSV(Comma-Separated Values)是纯文本表格格式,Excel 和数据库都能直接读写。
写入 CSV
import csv
rows = [
['name', 'age', 'city'],
['Alice', '25', 'Beijing'],
['Bob', '30', 'Shanghai'],
]
with open('data.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerows(rows)
Warning写 CSV 时必须加
newline=''。否则 Windows 下会在每行末尾多出一个空行。这是csv模块文档里的明确要求。
读取 CSV
import csv
with open('data.csv', 'r', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
print(row)
每行是一个列表,元素都是字符串。如果需要自动转数字,自己手动 int() / float()。
用字典读写
如果表头固定,用 DictReader 和 DictWriter 更直观:
import csv
with open('data.csv', 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
print(f"{row['name']} 住在 {row['city']}")
with open('output.csv', 'w', newline='', encoding='utf-8') as f:
fieldnames = ['name', 'age', 'city']
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerow({'name': 'Carol', 'age': '28', 'city': 'Shenzhen'})
字典方式代码可读性更好,而且不依赖列的顺序。
三种格式怎么选
| 格式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| pickle | 支持任意 Python 对象 | 只限 Python,有安全风险 | 临时缓存、内部数据传递 |
| JSON | 跨语言、人类可读、安全 | 类型支持有限 | API 接口、配置文件、数据交换 |
| CSV | 简单、Excel 兼容 | 不支持嵌套结构 | 表格数据导出、简单数据集 |
Tip如果要序列化复杂的嵌套数据结构,且需要跨语言,
pickle和csv都不合适。JSON 是默认选择。如果 JSON 也不够(比如需要二进制数据),考虑 MessagePack、Protobuf 等更高效的格式。
小结
pickle功能最强,但只限 Python 且不安全,别用来处理不可信数据。json是通用标准,适合 API 和配置文件,注意处理不支持的数据类型。csv适合简单表格,用DictReader/DictWriter代码更优雅。- 持久化前想清楚:数据是给谁用的?要不要跨语言?要不要人类可读?
序列化是连接「程序内存」和「外部世界」的桥梁。选对格式,数据就能顺畅地在文件、网络、数据库之间流动。
来源:参考了 runoob「Python Pickle 模块」和「Python JSON」、liaoxuefeng「序列化」、pythondoc「读写结构化数据」等,改写后所得。