pickle用于Python对象二进制序列化,仅限可信Python环境;不安全,禁用于不可信数据;不跨语言;需二进制模式读写;不支持lambda、文件句柄等对象。

用 pickle 保存对象最直接,但只适合 Python 内部用
如果数据是纯 Python 对象(比如 dict、list、自定义类实例),且只在 Python 环境里读写,pickle 是最快捷的选择。Python 3.10 默认使用 protocol 4,兼容性比老版本好,但依然不跨语言。
常见错误:用 pickle 存 lambda、闭包、带文件句柄或线程对象的实例——会直接抛 AttributeError 或 PicklingError。
- 必须以二进制模式打开文件:
open("data.pkl", "wb")写,open("data.pkl", "rb")读 - 避免用
pickle.dump(obj, f)后再手动f.close(),推荐用with语句确保写入完成 - 若对象很大,考虑用
pickle.HIGHEST_PROTOCOL(3.10 中即 protocol 5)提升效率,但需确认所有读取端也支持 Python 3.8+
import pickle
data = {"name": "Alice", "scores": [89, 92, 78]}
with open("data.pkl", "wb") as f:
pickle.dump(data, f)
用 json 存结构化数据,兼顾可读性和跨语言
当数据是基础类型(str、int、float、bool、None、list、dict)且需要人工查看、调试或被其他语言读取时,json 是更安全的选择。
常见错误:直接传入 datetime、bytes、set 或自定义对象——会报 TypeError: Object of type X is not JSON serializable。
立即学习“Python免费学习笔记(深入)”;
- 用
json.dump(obj, f)写文件,json.load(f)读文件;注意默认是文本模式("w"/"r") - 中文别漏掉
ensure_ascii=False,否则变成u4f60u597d - 时间戳建议转成 ISO 字符串:
dt.isoformat(),而不是直接塞datetime对象
import json
from datetime import datetime
data = {"created": datetime.now().isoformat(), "tags": ["python", "3.10"]}
with open("data.json", "w", encoding="utf-8") as f:
json.dump(data, f, ensure_ascii=False, indent=2)
用 sqlite3 管理多表/查询需求,比文件更可靠
一旦数据量变大、字段增多、需要增删改查或加索引,硬塞进单个 pickle 或 json 文件就容易出问题:读写冲突、加载慢、没法部分更新。
常见错误:每次操作都 connect + close,或者忘记 commit() 导致写入丢失;还有用字符串拼接 SQL 引发注入(哪怕本地文件也不该放松)。
- SQLite 是内嵌数据库,无需安装服务,
sqlite3是标准库,开箱即用 - 建表时明确字段类型(如
TEXT、INTEGER、REAL),避免后期类型混乱 - 用参数化查询:
cursor.execute("INSERT INTO logs VALUES (?, ?)", (msg, ts)),别用f"INSERT ... '{msg}'"
import sqlite3
conn = sqlite3.connect("app.db")
conn.execute("CREATE TABLE IF NOT EXISTS config (key TEXT, value TEXT)")
conn.execute("INSERT INTO config VALUES (?, ?)", ("version", "3.10"))
conn.commit()
conn.close()
序列化路径和权限问题最容易被忽略
代码在开发机跑通,一到服务器或 Docker 容器里就报 PermissionError 或 FileNotFoundError,往往不是序列化逻辑的问题,而是路径没想清楚。
-
"data.pkl"是相对路径,实际写入位置取决于当前工作目录(os.getcwd()),不是脚本所在目录(__file__) - 写入前先确保目录存在:
os.makedirs(os.path.dirname(path), exist_ok=True) - Windows 下路径分隔符用
os.path.join()或pathlib.Path,别硬写"data\sub\file.json" - 如果程序以非 root 用户运行(比如 systemd service),检查目标目录是否可写
复杂点在于:不同环境对“持久化”的理解不同——笔记本上存桌面没问题,生产环境可能要求写入 /var/lib/myapp/ 并由 systemd 设置目录权限。这点不提前约定,后期运维会卡住。


















