1 概念
将对象转换为可保存状态(例如字节流、文本表示等)称为序列化,而反序列化将数据从上述格式转换回对象。
序列化格式会将内存中重建对象所需的所有信息保留在与序列化时相同的状态。
在 Python 中提供了一个 pickle 模块,pickle 模块实现了二进制协议。支持我们的对象数据的序列和反序列化。
2 存储 Python 原生对象:pickle 模块
pickle 模块能够让我们直接在文件中存储几乎任何 Python 对象的高级工具,同时不需要我们对字符串进行来回转换。它像是超级通用的数据格式化和解析工具。
pickle 包可用于执行 pickling 和 unpickling 操作。Python 中的 pickling
用于描述将 Python 对象转换为字节流的过程,也被称为序列化(serialization 或者 marshalling、flattening)。
unpickling
反之,将字节流(来自二进制文件或字节对象)转换为对象结构,这个过程又被叫反序列化(De-serialization)。
Python 的 pickle 模块基本上由四个方法组成:
dump()
pickle.dump(obj, file, protocol=None, *, fix_imports=True, buffer_callback=None)
dumps()
pickle.dumps(obj, protocol=None, *, fix_imports=True, buffer_callback=None)
load()
pickle.load(file, *, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
loads()
pickle.loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict", buffers=None)
序列化到字符串
前两个方法是在 pickling 过程中使用的,另外两个是在 unpickling 过程中使用的。dump()
和 dumps()
的唯一区别是,前者创建一个包含序列化结果的文件,而后者则返回一个字符串。
为了区分 dumps()
和 dump()
,记住函数名后面的 s 代表字符串是很有帮助的。同样的概念也适用于loads()
和 load()
。第一个函数对一个字符串进行操作。第二个读取一个文件以开始解压过程。
假如有如下的例子:
import pickle my_dic = {"k1", 20, "k2", 22} str_dic = pickle.dumps(my_dic) print("序列化后 str_dic: ", str_dic) my_dic2 = pickle.loads(str_dic) print("反序列化的 my_dic2: ", my_dic2)
输出结果:
$ python pickle_dumps.py 序列化后 str_dic: b'\x80\x04\x95\x13\x00\x00\x00\x00\x00\x00\x00\x8f\x94(\x8c\x02k2\x94\x8c\x02k1\x94K\x14K\x16\x90.' 反序列化的 my_dic2: {'k2', 'k1', 20, 22}
序列化到文件
import pickle students = { "Name": ["张三", "法外狂徒", "张麻子"], "Major": ["社会学", "法律", "经济"] } print(students)
运行结果:
{'Name': ['张三', '法外狂徒', '张麻子'], 'Major': ['社会学', '法律', '经济']}
让我们尝试将学生对象 pickling 到二进制文件中。我们可以使用 dump()
函数来做到这一点。它需要两个参数:被 pickled 的对象和要写入数据的 File 对象。
以下代码将数据 pickle 到一个新文件 stu.txt,该文件将在脚本运行的同一目录中创建:
import pickle students = { "Name": ["张三", "法外狂徒", "张麻子"], "Major": ["社会学", "法律", "经济"] } print(students) stu_file = open('stu.txt', 'wb') pickle.dump(students, stu_file) stu_file.close()
运行完后,则会在同目录下多一个 stu.txt 文件,如下:
常规文本编辑器无法查看创建的文件的内容,因为它是二进制数据,并不意味着以人类可读的格式存储。要读取此信息,我们必须解压缩或反序列化此数据。我们可以使用 load()
函数来做到这一点!
load()
函数读取 pickled 文件的内容并返回通过读取数据构造的对象。对象的类型及其状态取决于文件的内容。
由于我们已经保存了一个包含学生姓名和专业的字典:这个具有相同条目的对象被重建。
让我们将刚刚创建的 pickled 文件 stu.txt 读回 Python 对象并打印其内容,新建一个 Python 文件,写入如下代码:
import pickle stu_file = open("stu.txt", "rb") stu_data = pickle.load(stu_file) stu_file.close() print("学生数据:", stu_data)
运行结果:
$ python3 unpickledtest.py 学生数据: {'Name': ['张三', '法外狂徒', '张麻子'], 'Major': ['社会学', '法律', '经济']}