Python 标准库中的数据存储与序列化:json、pickle、csv
当需要将数据写入文件或通过网络传输时,序列化(Serialization) 是必不可少的步骤。Python 为此提供了三种截然不同的标准工具:json、pickle、csv。

json:可读的文本格式,便于跨语言交换pickle:一种能将 Python 对象原样保存的二进制格式,功能强大但存在安全隐患csv:最简洁的文本格式,常用于表格数据,通用性高
本文将根据“想要存储或使用的数据类型”来阐述这三种模块的选择思路。
1. JSON
1.1 概述
JSON(JavaScript Object Notation)是基于文本且语言无关的格式。它广泛用于配置文件、API 响应/请求、日志等“与其他系统交互”的场景。在 Python 中直接使用 json 模块即可处理。
1.2 核心 API(常用)
json.dump(obj, fp, ...)/json.load(fp, ...):文件读写json.dumps(obj, ...)/json.loads(s, ...):字符串转换/恢复
值得记住的选项:
ensure_ascii=False:不对非 ASCII 字符进行转义,保留原文indent=2:格式化输出default=...:为 JSON 不认识的类型提供自定义转换
1.3 使用示例(基本)
import json
data = {
"name": "Alice",
"age": 30,
"skills": ["Python", "Data Science"]
}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
with open("data.json", "r", encoding="utf-8") as f:
loaded = json.load(f)
print(loaded)
1.4 解决 JSON 的“类型限制”
JSON 原生只支持 dict、list、str、int/float、bool、None。例如 datetime 无法直接序列化。这时可以使用 default 参数。
import json
from datetime import datetime, timezone
payload = {"created_at": datetime.now(timezone.utc)}
def to_jsonable(obj):
if isinstance(obj, datetime):
return obj.isoformat()
raise TypeError(f"Not JSON serializable: {type(obj)!r}")
s = json.dumps(payload, default=to_jsonable, ensure_ascii=False)
print(s)
1.5 优缺点
优点
- 语言无关,易于交换/共享
- 文本格式,易于调试和版本控制
- 与
pickle不同,加载时不会执行代码
缺点
- 类型表达有限(如
datetime、set、Decimal、二进制数据) - 对大数据而言,体积和速度可能不如二进制格式
2. Pickle
2.1 概述
pickle 是一种 将 Python 对象原样保存 的序列化方式。其结果是二进制数据(bytes),加载后几乎恢复为原始对象。
pickle 特别适用于:
- 想保存复杂的 Python 对象(自定义类实例、嵌套结构、训练好的模型等)
- 不需要与其他语言共享数据
相反,以下情况应避免使用:
- 需要从不可信来源加载数据(
pickle.load()可能执行恶意代码) - 与其他语言/系统交换数据
2.2 核心 API(最常用 4 个)
pickle.dump(obj, file, protocol=...):对象 → 文件(二进制)pickle.load(file):文件 → 对象pickle.dumps(obj, protocol=...):对象 → bytespickle.loads(data):bytes → 对象
import pickle
data = {"a": [1, 2, 3], "b": ("x", "y")}
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
with open("data.pkl", "rb") as f:
loaded = pickle.load(f)
print(loaded)
2.3 protocol 是什么,为什么要关注?
protocol 是 pickle 用于存储数据的 格式版本。不同版本会影响文件大小、速度和支持的功能。
- 未指定时,Python 会选择“当前环境中最合适的默认值”。
- 通常保持默认即可。
- 需要手动指定时,主要有两种情况: 1. 与旧 Python 版本兼容(使用较低协议) 2. 追求文件大小/速度最优(使用最高协议)
import pickle
with open("data.pkl", "wb") as f:
pickle.dump({"x": 1}, f, protocol=pickle.HIGHEST_PROTOCOL)
2.4 Pickle 的真正注意点(重要)
pickle.load() / pickle.loads() 会执行数据中包含的恢复逻辑。因此,从不可信来源加载 pickle 可能导致意外行为。
- 安全做法:不要打开未知来源的
.pkl文件。 - 若需共享/交换,优先使用
json等文本格式。
2.5 优缺点
优点
- 能保存几乎所有 Python 对象
- 通常比
json更快、更简洁(尤其是复杂对象)
缺点
- 安全风险(不可信数据不可加载)
- 仅 Python 可读,无法与其他语言共享
- 类定义变更可能导致旧的 pickle 文件无法加载
3. CSV
3.1 概述
CSV(Comma-Separated Values)是最简单的表格数据格式。常见于电子表格、数据导入/导出、日志转储等场景。
3.2 核心 API(常用)
csv.reader/csv.writer:基于列表csv.DictReader/csv.DictWriter:基于字典(更常用)
3.3 使用示例(DictWriter/DictReader)
import csv
data = [
{"name": "Alice", "age": 30, "city": "Seoul"},
{"name": "Bob", "age": 25, "city": "Busan"},
]
with open("people.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["name", "age", "city"])
writer.writeheader()
writer.writerows(data)
with open("people.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
loaded = list(reader)
print(loaded)
3.4 CSV 的三大注意点
- 一定要使用
newline="":尤其在 Windows 系统上,可避免双行换行。 - 所有字段默认是字符串:读取后需手动转换。
- 分隔符/引号/换行可能出现在数据中:使用
csv模块可安全处理。
3.5 优缺点
优点
- 极轻量,几乎所有工具都能读写
- 对表格数据非常直观
缺点
- 难以表达嵌套结构(列表/字典嵌套)
- 缺少类型信息,需手动转换
4. 比较与选择指南
| 项目 | JSON | Pickle | CSV |
|---|---|---|---|
| 语言兼容 | 非常好 | 仅 Python | 非常好 |
| 可读性 | 高 | 低(二进制) | 高 |
| 类型表达 | 限制 | 极高 | 限制 |
| 安全性 | 相对安全 | 需谨慎 | 相对安全 |
| 数据结构 | 树形(嵌套) | “Python 对象原样” | 表格(行/列) |
一句话总结:
- 与其他系统交互 →
json - 完整保存 Python 对象 →
pickle(但要严格控制来源) - 行/列导出 →
csv
5. 同一数据三种存储/恢复示例
以下示例展示如何使用 json、pickle、csv 对同一数据进行存储和读取。
import json, pickle, csv
data = [
{"id": 1, "name": "Alice", "score": 95.5},
{"id": 2, "name": "Bob", "score": 88.0},
]
# 1) JSON
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
with open("data.json", "r", encoding="utf-8") as f:
json_loaded = json.load(f)
# 2) Pickle
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
with open("data.pkl", "rb") as f:
pickle_loaded = pickle.load(f)
# 3) CSV
with open("data.csv", "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["id", "name", "score"])
writer.writeheader()
writer.writerows(data)
with open("data.csv", "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
csv_loaded = [
{"id": int(row["id"]), "name": row["name"], "score": float(row["score"])}
for row in reader
]
print(json_loaded)
print(pickle_loaded)
print(csv_loaded)
要点:
- CSV 读取后需手动转换类型。
- Pickle 方便但需谨慎管理加载来源。
6. 结语
仅凭 Python 标准库,便能满足数据存储与序列化的广泛需求。
- 需要跨语言共享 →
json - 想保留完整 Python 对象 →
pickle - 想以表格形式导出 →
csv
根据数据形态与目的选择合适的模块,即可快速高效地完成存储与恢复。
目前没有评论。