跳到主要内容

序列化

程序运行中变量都在内存中,程序结束即被回收。序列化:把变量从内存变成可存储或可传输的形式(Python 称 pickling,其他语言多称 serialization)。反序列化:从序列化形式读回内存(unpickling)。Python 常用 pickle(仅 Python)和 json(跨语言、Web 标准)。

1. pickle:Python 专用序列化

  • import pickle
  • pickle.dumps(obj):把任意对象序列化为 bytes,不写文件。
  • pickle.dump(obj, file):序列化并直接写入 file-like Object(需以 'wb' 等二进制模式打开)。
  • pickle.loads(bytes):从 bytes 反序列化出对象。
  • pickle.load(file):从 file-like Object('rb'直接反序列化出对象。
  • 写入磁盘的内容是二进制,人类不可读;反序列化得到的是内容相同的新对象,与原来的对象不是同一个。
import pickle
d = dict(name='Bob', age=20, score=88)
pickle.dumps(d) # bytes
with open('dump.txt', 'wb') as f:
pickle.dump(d, f)
with open('dump.txt', 'rb') as f:
d2 = pickle.load(f) # 得到与 d 内容相同的 dict
  • 局限仅适用于 Python,且不同 Python 版本可能不兼容;适合保存“不重要、反序列化失败也无所谓”的数据。

2. JSON:跨语言标准格式

  • 在不同语言间传递对象,需用标准格式JSON 是字符串,各语言都能读,便于存盘和网络传输。
  • import json
  • json.dumps(obj):把 Python 对象序列化为 str(标准 JSON 字符串)。
  • json.dump(obj, file):序列化并写入 file-like Object。
  • json.loads(s):把 JSON 字符串反序列化为 Python 对象。
  • json.load(file):从 file-like Object 读取并反序列化
  • JSON 标准使用 UTF-8 编码,与 Python 的 str 转换无问题。
JSON 类型Python 类型
{}dict
[]list
"..."str
数字int / float
true/falseTrue/False
nullNone
import json
d = dict(name='Bob', age=20, score=88)
json.dumps(d) # '{"age": 20, "score": 88, "name": "Bob"}'
json_str = '{"age": 20, "score": 88, "name": "Bob"}'
json.loads(json_str) # {'age': 20, 'score': 88, 'name': 'Bob'}

3. JSON 进阶:自定义类的序列化与反序列化

  • dict 可直接 json.dumps()class 实例不能直接序列化,会报 TypeError: ... is not JSON serializable
  • 序列化类实例:为 json.dumps(obj, default=转换函数) 提供 default;转换函数把任意对象变成可被 JSON 序列化的类型(通常是 dict)。
def student2dict(std):
return {'name': std.name, 'age': std.age, 'score': std.score}

json.dumps(s, default=student2dict)
  • 通用写法json.dumps(s, default=lambda obj: obj.__dict__),利用多数实例的 __dict__ 属性;定义了 __slots__ 的类没有 __dict__,不能这样用。
  • 反序列化为类实例json.loads(s, object_hook=转换函数);转换函数接收 dict,返回自定义类实例。
def dict2student(d):
return Student(d['name'], d['age'], d['score'])

json.loads(json_str, object_hook=dict2student) # 得到 Student 实例

4. 中文与 ensure_ascii

  • json.dumps(obj, ensure_ascii=True)(默认):非 ASCII 字符(如中文)会被转成 \uXXXX
  • json.dumps(obj, ensure_ascii=False):中文等直接保留在字符串中,便于阅读。

5. 小结

模块适用场景序列化结果跨语言 / 版本
pickle仅 Python 内部持久化bytes否,版本敏感
json存盘、网络、跨语言str (JSON)
  • pickle:Python 专用,接口为 dumps/dumploads/load
  • json:通用、Web 标准;dumps/loads 接口简单,通过 defaultobject_hook 可扩展为支持自定义类。

练习

对中文进行 JSON 序列化时,分别使用 ensure_ascii=Trueensure_ascii=False,观察输出差异。

import json
obj = dict(name='小明', age=20)
json.dumps(obj, ensure_ascii=True)
json.dumps(obj, ensure_ascii=False)