序列化是指将对象转换成一种易于存储或传输的格式的过程。在 Python 中,这意味着将复杂的数据结构,如对象或字典,转换成字节流。
为什么我们要使用序列化?
序列化允许数据容易地保存到磁盘或通过网络传输,并且可以在以后重新构造回原来的形式。对于保存游戏状态、存储用户偏好或在不同系统之间交换数据等任务来说,它是重要的。
Python 中的序列化库
Python 提供了几种序列化库,每种都有自己的优点。以下是 Python 中一些常用的序列化库的详细介绍:
-
Pickle - 这是 Python 内置的用于序列化和反序列化 Python 对象的模块。它简单易用,但仅限于 Python,并且如果使用不可信的数据可能会有安全问题。
-
JSON - JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人类阅读并且易于解析。它非常适合 Web API 和跨平台通信。
-
YAML - YAML 是一种人类可读的数据序列化标准,同样易于人类和机器读写。它支持复杂的结构,通常用于配置文件中。
使用 Pickle 模块进行序列化
Python 中的 pickle
模块用于序列化和反序列化对象。序列化,也称为 pickling,涉及将 Python 对象转换成字节流,然后可以将其存储在文件中或通过网络传输。
反序列化,或 unpickling,是相反的过程,即将字节流转换回 Python 对象。
序列化一个对象
我们可以使用 dump()
函数序列化一个对象,并将其写入文件。文件必须以二进制写模式('wb')打开。
示例
在下面的例子中,一个字典被序列化并写入名为 "data.pkl" 的文件中:
import pickle
data = {'name': 'Alice', 'age': 30, 'city': 'New York'}
with open('data.pkl', 'wb') as file:
pickle.dump(data, file)
print("File created!!")
当上述代码被执行时,字典对象的字节表示将会被存储在 data.pkl 文件中。
反序列化一个对象
要反序列化或 unpickle 对象,你可以使用 load()
函数。文件必须以二进制读模式('rb')打开如下所示:
import pickle
with open('data.pkl', 'rb') as file:
data = pickle.load(file)
print(data)
这将从 "data.pkl" 读取字节流,并将其转换回原来的字典形式,如下所示:
{'name': 'Alice', 'age': 30, 'city': 'New York'}
Pickle 协议
协议是在构建和解构 Python 对象到/从二进制数据时使用的约定。
pickle
模块支持不同的序列化协议,一般来说,较高的协议提供了更多的特性和更好的性能。目前 pickle
模块定义了六个不同的协议,如下所示:
序号 |
协议版本 & 描述 |
1 |
Protocol 版本 0 |
|
原始的“人类可读”协议,与早期版本兼容。 |
2 |
Protocol 版本 1 |
|
旧的二进制格式也与早期版本的 Python 兼容。 |
3 |
Protocol 版本 2 |
|
在 Python 2.3 中引入,提供了对新式类的有效 pickling。 |
4 |
Protocol 版本 3 |
|
在 Python 3.0 中加入,建议在需要与其他 Python 3 版本兼容时使用。 |
5 |
Protocol 版本 4 |
|
在 Python 3.4 中引入,增加了对非常大对象的支持。 |
6 |
Protocol 版本 5 |
|
在 Python 3.8 中引入,增加了对带外数据的支持。 |
你可以通过将协议作为参数传递给 pickle.dump()
函数来指定协议。
要了解你的 Python 安装的最高和默认协议版本,请使用 pickle
模块中定义的以下常量:
>>> import pickle
>>> pickle.HIGHEST_PROTOCOL
5
>>> pickle.DEFAULT_PROTOCOL
4
Pickler 和 Unpickler 类
Python 中的 pickle
模块还定义了 Pickler
和 Unpickler
类,以便更详细地控制序列化和反序列化过程。Pickler
类将 pickle 数据写入文件,而 Unpickler
类从文件中读取二进制数据并重构原始的 Python 对象。
使用 Pickler 类
要使用 Pickler
类序列化 Python 对象,你可以遵循以下步骤:
from pickle import Pickler
with open("data.txt", "wb") as f:
dct = {'name': 'Ravi', 'age': 23, 'Gender': 'M', 'marks': 75}
Pickler(f).dump(dct)
print("Success!!")
执行上述代码后,字典对象的字节表示将会存储在 "data.txt" 文件中。
使用 Unpickler 类
要使用 Unpickler
类从二进制文件中反序列化数据,你可以这样做:
from pickle import Unpickler
with open("data.txt", "rb") as f:
dct = Unpickler(f).load()
print(dct)
我们得到的输出如下:
{'name': 'Ravi', 'age': 23, 'Gender': 'M', 'marks': 75}
序列化自定义类对象
pickle
模块还可以序列化和反序列化自定义类。类定义必须在序列化和反序列化时都可用。
示例
在这个例子中,一个 “Person” 类的实例被序列化然后反序列化,保持了对象的状态:
import pickle
class Person:
def __init__(self, name, age, city):
self.name = name
self.age = age
self.city = city
person = Person('Alice', 30, 'New York')
with open('person.pkl', 'wb') as file:
pickle.dump(person, file)
with open('person.pkl', 'rb') as file:
person = pickle.load(file)
print(person.name, person.age, person.city)
执行上述代码后,我们得到如下输出:
Alice 30 New York
Python 标准库还包括 marshal
模块,它用于 Python 对象的内部序列化。不像 pickle
是为通用用途设计的,marshal
主要由 Python 自身使用(例如,用于写入 .pyc 文件)。
由于潜在的 Python 版本之间的兼容性问题,一般不推荐用于通用序列化。
使用 JSON 进行序列化
JSON(JavaScript Object Notation)是一种流行的数据交换格式。它易于人类阅读,易于编写,并且语言独立,使其成为序列化的理想选择。
Python 通过 json
模块提供内置支持,允许你将数据序列化和反序列化为 JSON 格式。
序列化
序列化是将 Python 对象转换成 JSON 字符串或将它写入文件的过程。
示例:序列化数据到 JSON 字符串
在下面的例子中,我们使用 json.dumps()
函数将 Python 字典转换成 JSON 字符串:
import json
data = {"name": "Alice", "age": 25, "city": "San Francisco"}
json_string = json.dumps(data)
print(json_string)
上述代码的输出如下:
{"name": "Alice", "age": 25, "city": "San Francisco"}
示例:序列化数据并写入文件
在这里,我们使用 json.dump()
函数直接将序列化的 JSON 数据写入文件:
import json
data = {"name": "Alice", "age": 25, "city": "San Francisco"}
with open("data.json", "w") as f:
json.dump(data, f)
print("Success!!")
反序列化
反序列化是将 JSON 字符串转换回 Python 对象或将它从文件中读出的过程。
示例:反序列化 JSON 字符串
在下面的例子中,我们使用 json.loads()
函数将 JSON 字符串转换回 Python 字典:
import json
json_string = '{"name": "Alice", "age": 25, "city": "San Francisco"}'
loaded_data = json.loads(json_string)
print(loaded_data)
它将产生以下输出:
{'name': 'Alice', 'age': 25, 'city': 'San Francisco'}
使用 JSON 进行反序列化
在此示例中,我们使用 json.load()
函数从文件中读取 JSON 数据并将其转换为 Python 字典:
import json
with open("data.json", "r") as f:
loaded_data = json.load(f)
print(loaded_data)
所获得的输出如下:
{'name': 'Alice', 'age': 25, 'city': 'San Francisco'}
使用 YAML 进行序列化
YAML(YAML Ain't Markup Language)是一种人类可读的数据序列化标准,通常用于配置文件和数据交换。
Python 通过 pyyaml
包支持 YAML 的序列化和反序列化,首先需要安装该包,如下所示:
pip install pyyaml
示例:序列化数据并写入 YAML 文件
在下面的例子中,yaml.dump()
函数将 Python 字典 data
转换成 YAML 字符串并写入文件 "data.yaml"。
default_flow_style
参数确保 YAML 输出是以扩展格式呈现,更具人类可读性:
import yaml
data = {"name": "Emily", "age": 35, "city": "Seattle"}
with open("data.yaml", "w") as f:
yaml.dump(data, f, default_flow_style=False)
print("Success!!")
示例:从 YAML 文件反序列化数据
这里,yaml.safe_load()
函数用于安全地从 "data.yaml" 加载 YAML 数据,并将其转换成 Python 字典(loaded_data
):
使用 safe_load()
是出于安全原因,因为它只允许基本的 Python 数据类型,并避免执行 YAML 文件中的任意代码。
import yaml
with open("data.yaml", "r") as f:
loaded_data = yaml.safe_load(f)
print(loaded_data)
产生的输出如下所示:
{'age': 35, 'city': 'Seattle', 'name': 'Emily'}