Python - 序列化



Python中的序列化

序列化是指将对象转换为易于存储、传输或稍后重建的格式的过程。在Python中,这涉及将复杂的数据结构(例如对象或字典)转换为字节流。

我们为什么要使用序列化?

序列化允许数据轻松保存到磁盘或通过网络传输,然后恢复到其原始形式。这对于保存游戏状态、存储用户首选项或在不同系统之间交换数据等任务非常重要。

Python中的序列化库

Python 提供了多个序列化库,每个库都有其自身的优势。以下是Python中一些常用序列化库的详细概述:

  • Pickle − 这是Python内置的用于序列化和反序列化Python对象的模块。它易于使用,但特定于Python,如果用于不受信任的数据,则可能存在安全隐患。

  • JSON − JSON(JavaScript 对象表示法)是一种轻量级的数据交换格式,它是人类可读的并且易于解析。它非常适合 Web API 和跨平台通信。

  • YAML − YAML:(YAML Ain't Markup Language)是一种人类可读的数据序列化标准,易于人类和机器读取和写入。它支持复杂的数据结构,通常用于配置文件。

使用Pickle模块进行序列化

Python 中的 pickle 模块用于序列化和反序列化对象。序列化,也称为 **pickling**,涉及将 Python 对象转换为字节流,然后可以将其存储在文件中或通过网络传输。

反序列化或 **unpickling** 是相反的过程,即将字节流转换回 Python 对象。

序列化对象

我们可以使用 `dump()` 函数序列化对象并将其写入文件。文件必须以二进制写入模式 ('wb') 打开。

示例

在下面的示例中,一个字典被序列化并写入名为“data.pkl”的文件:

import pickle

data = {'name': 'Alice', 'age': 30, 'city': 'New York'}

# Open a file in binary write mode
with open('data.pkl', 'wb') as file:
   # Serialize the data and write it to the file
   pickle.dump(data, file)
   print ("File created!!")   

执行上述代码时,字典对象的字节表示将存储在 data.pkl 文件中。

反序列化对象

要反序列化或解包对象,可以使用 `load()` 函数。文件必须以二进制读取模式 ('rb') 打开,如下所示:

import pickle

# Open the file in binary read mode
with open('data.pkl', 'rb') as file:
   # Deserialize the data
   data = pickle.load(file)
print(data)

这将从“data.pkl”读取字节流并将其转换回原始字典,如下所示:

{'name': 'Alice', 'age': 30, 'city': 'New York'}

Pickle 协议

协议是用于在将 Python 对象构造/解构为/从二进制数据中使用的约定。

该 `pickle` 模块支持不同的序列化协议,更高的协议通常提供更多功能和更好的性能。目前,`pickle` 模块定义了 6 种不同的协议,如下所示:

序号 协议和描述
1

协议版本 0

原始“人类可读”协议,与早期版本向后兼容。

2

协议版本 1

旧的二进制格式也与早期版本的 Python 兼容。

3

协议版本 2

在 Python 2.3 中引入,提供对新式类的有效序列化。

4

协议版本 3

在 Python 3.0 中添加。当需要与其他 Python 3 版本兼容时推荐使用。

5

协议版本 4

在 Python 3.4 版本中引入。它增加了对超大对象的支持。

6

协议版本 5

在 Python 3.8 版本中引入。它增加了对带外数据(out-of-band data)的支持。

可以通过将其作为参数传递给 `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

# Open a file in binary write mode
with open("data.txt", "wb") as f:
   # Create a dictionary
   dct = {'name': 'Ravi', 'age': 23, 'Gender': 'M', 'marks': 75}
   # Create a Pickler object and write the dictionary to the file
   Pickler(f).dump(dct)
   print ("Success!!")

执行上述代码后,字典对象的字节表示将存储在 "data.txt" 文件中。

使用 Unpickler 类

要使用 Unpickler 类从二进制文件反序列化数据,可以执行以下操作:

from pickle import Unpickler

# Open the file in binary read mode
with open("data.txt", "rb") as f:
   # Create an Unpickler object and load the dictionary from the file
   dct = Unpickler(f).load()
   # Print the dictionary
   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

# Create an instance of the Person class
person = Person('Alice', 30, 'New York')

# Serialize the person object
with open('person.pkl', 'wb') as file:
   pickle.dump(person, file)

# Deserialize the person object
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 对象表示法)是一种流行的数据交换格式。它易于阅读、易于编写且与语言无关,非常适合序列化。

Python 通过 `json` 模块提供对 JSON 的内置支持,该模块允许您将数据序列化和反序列化为 JSON 格式。

序列化

序列化是将 Python 对象转换为 JSON 字符串或将其写入文件的过程。

示例:将数据序列化为 JSON 字符串

在下面的示例中,我们使用 `json.dumps()` 函数将 Python 字典转换为 JSON 字符串:

import json

# Create a dictionary
data = {"name": "Alice", "age": 25, "city": "San Francisco"}

# Serialize the dictionary to a JSON string
json_string = json.dumps(data)
print(json_string)  

上述代码的输出如下:

{"name": "Alice", "age": 25, "city": "San Francisco"}

示例:序列化数据并写入文件

在这里,我们使用 `json.dump()` 函数将序列化的 JSON 数据直接写入文件:

import json

# Create a dictionary
data = {"name": "Alice", "age": 25, "city": "San Francisco"}

# Serialize the dictionary and write it to a file
with open("data.json", "w") as f:
   json.dump(data, f)
   print ("Success!!")

反序列化

反序列化是将 JSON 字符串转换回 Python 对象或从文件读取它的过程。

示例:反序列化 JSON 字符串

在以下示例中,我们使用 `json.loads()` 函数将 JSON 字符串转换回 Python 字典:

import json

# JSON string
json_string = '{"name": "Alice", "age": 25, "city": "San Francisco"}'

# Deserialize the JSON string into a Python dictionary
loaded_data = json.loads(json_string)
print(loaded_data)  

输出结果如下:

{'name': 'Alice', 'age': 25, 'city': 'San Francisco'}

示例:从文件反序列化数据

在这里,我们使用 `json.load()` 函数从文件读取 JSON 数据并将其转换为 Python 字典:

import json

# Open the file and load the JSON data into a Python dictionary
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 字典数据转换为 YAML 字符串并将其写入 "data.yaml" 文件。

`default_flow_style` 参数确保 YAML 输出更易于阅读,并具有扩展格式:

import yaml

# Create a Python dictionary
data = {"name": "Emily", "age": 35, "city": "Seattle"}

# Serialize the dictionary and write it to a YAML file
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

# Deserialize data from a YAML file
with open("data.yaml", "r") as f:
   loaded_data = yaml.safe_load(f)
   print(loaded_data)  

产生的输出如下所示:

{'age': 35, 'city': 'Seattle', 'name': 'Emily'}
广告