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'}
廣告