Python 全攻略 第10節:Chapter 5- I/O in Python 88~95

88.~92 project- Tic Tac Toe Game
93. Serialization and Deserialization
94. Pickle
95. Shelve

93. Serialization and Deserialization

在程式設計中,**序列化(Serialization)和反序列化(Deserialization)**是兩個常見的概念,主要與資料的轉換和儲存有關。
簡單來說,這兩個過程是資料在不同形式之間轉換的過程。

1. 序列化 (Serialization)

序列化是將資料結構或物件狀態轉換為可以儲存或傳輸的格式,通常是二進制或字串格式。
這個過程使得物件可以被儲存在檔案中、傳輸到網路上、或儲存在資料庫中,
且能夠在未來再進行反序列化(還原)以恢復成原來的物件。

簡單的例子:
假設你有一個 Python 字典 {“name”: “Alice”, “age”: 30},你想將它寫入文件中,
或者將它發送到網路上,你需要將它「序列化」成某種格式(如 JSON 或 Pickle 格式)。
在這種情況下,序列化就是將 Python 物件轉換為字串或二進制格式,以便進行儲存或傳輸。
在 Python 中,常用的序列化格式包括:

  • JSON(JavaScript Object Notation):通常用於資料交換,尤其在 Web 開發中。
  • Pickle:Python 自有的序列化格式,適用於 Python 物件的儲存和重建。

2. 反序列化 (Deserialization)

反序列化是序列化的反向過程,將儲存或傳輸過來的資料恢復為原來的物件或資料結構。也就是說,將二進制或字串格式的資料轉換回程式可以處理的物件。

簡單的例子:
假設你有一個序列化後的資料(例如 JSON 格式的字串)‘{“name”: “Alice”, “age”: 30}’,你想將它轉換回 Python 字典物件,這時候就需要進行反序列化。
在 Python 中,常用的反序列化方式包括:

  • JSON 反序列化(json.loads())
  • Pickle 反序列化(pickle.load())
  • 序列化與反序列化的應用範例

JSON 格式的序列化與反序列化:

import json

# 物件
person = {"name": "Alice", "age": 30}

# 序列化: 將 Python 字典轉換為 JSON 格式的字串
json_data = json.dumps(person)
print("Serialized data:", json_data)

# 反序列化: 將 JSON 格式的字串轉換回 Python 字典
person_object = json.loads(json_data)
print("Deserialized data:", person_object)

在這個例子中:

  • json.dumps():將 Python 字典轉換為 JSON 格式的字串,這就是序列化。
  • json.loads():將 JSON 格式的字串轉換回 Python 字典,這就是反序列化。

Pickle 格式的序列化與反序列化:

import pickle

# 物件
person = {"name": "Alice", "age": 30}

# 序列化: 將 Python 物件轉換為二進制格式
with open("person.pkl", "wb") as file:
    pickle.dump(person, file)

# 反序列化: 從檔案中讀取二進制格式並轉換回 Python 物件
with open("person.pkl", "rb") as file:
    loaded_person = pickle.load(file)
print("Deserialized data:", loaded_person)

在這個例子中:

  • pickle.dump():將 Python 物件轉換為二進制格式並儲存在檔案中,這就是序列化。
  • pickle.load():將檔案中的二進制資料反序列化回 Python 物件。

為什麼要使用序列化和反序列化?

儲存和傳輸資料
透過序列化,可以將複雜的資料結構(例如 Python 物件、字典、列表等)轉換為便於儲存或傳輸的格式。反序列化則可以將其轉換回原本的格式,讓程式能夠繼續處理這些資料。

Web API 與資料交換
網頁應用程序、API、微服務等經常使用 JSON 來序列化和反序列化資料,以便於在不同的系統之間進行資料交換。

儲存 Python 物件
在 Python 中,你可以使用 Pickle 模組來將物件儲存到磁碟上(例如:保存模型、訓練資料、程式狀態等),並在需要時反序列化回來。

避免資料丟失:
透過序列化,你可以保證資料在傳輸或儲存過程中不會丟失或改變,並且能夠以一致的方式還原。

結論

序列化是將資料結構或物件轉換為可以儲存或傳輸的格式(如字串或二進制)。
反序列化是將這些格式轉換回原來的資料結構或物件。
這些技術對於資料儲存、網路資料傳輸和跨平台應用程式的開發至關重要。

什麼是 Pickle?

Pickle 是 Python 提供的一個內建模組,
專門用於將 Python 物件序列化(serialize)和反序列化(deserialize)。它將 Python 物件轉換為二進制格式,便於儲存到檔案或傳輸到網路上,並且能夠隨時還原成原始的 Python 物件。

Pickle 的主要用途

  • 儲存 Python 物件到檔案:
    將變數(如列表、字典、類別等)儲存到磁碟,以便在未來的程式執行中重複使用。
  • 物件的網路傳輸:
    將 Python 物件序列化後,可以透過網路傳輸並在接收端反序列化還原。
  • 保存程式狀態:
    在某些情況下,可以用來保存程式的中間狀態,稍後繼續執行。

如何使用 Pickle?

  1. 匯入模組
    要使用 Pickle,首先要匯入 pickle 模組:
import pickle
  1. 將資料序列化並儲存到檔案
    使用 pickle.dump() 方法,可以將 Python 物件序列化後儲存在檔案中:
# 要儲存的物件
data = {"name": "Alice", "age": 30, "languages": ["Python", "C++", "Java"]}

# 打開檔案,以二進制寫入模式(wb)
with open("data.pkl", "wb") as file:
    pickle.dump(data, file)

print("資料已序列化並儲存到檔案 data.pkl")
  1. 從檔案中讀取資料並反序列化
    使用 pickle.load() 方法,可以將儲存的二進制格式資料反序列化為 Python 物件:
# 打開檔案,以二進制讀取模式(rb)
with open("data.pkl", "rb") as file:
    loaded_data = pickle.load(file)

print("從檔案中還原的資料:", loaded_data)

pickle常見情境:

  1. 保存複雜的 Python 資料結構
    當資料結構包含像是列表、字典,甚至自訂類別的物件,並且希望在稍後還原使用時,pickle 是一個快速且方便的工具。
    例如:
  • 中間處理結果的保存和讀取(如數據分析中的數據快取)。
  • 機器學習中訓練後的模型保存(如 scikit-learn 使用 pickle 保存模型)。
  1. 程序之間的數據傳遞
    如果有多個 Python 程序需要共享數據,可以透過 pickle 序列化資料,將其儲存到檔案或傳遞到其他程序。
    例如:
  • 保存狀態以供另一個程序讀取。
  • 透過網路或管道傳遞序列化的物件。
  1. 保存和還原工作進度
    如果程式執行需要很長時間,pickle 可用於保存執行的中間狀態,避免重複執行相同的操作。
    例如:
    長時間運行的數據處理工作中保存進度,然後在程序崩潰或中斷時還原。

  2. 快速測試或臨時保存
    在開發和測試中,pickle 可以用來臨時保存數據以快速調試或測試功能。

使用 pickle 的注意事項

安全性問題:
pickle 無法防範惡意數據,因此不要反序列化(pickle.load)不受信任的來源的數據。
與 JSON 的選擇:

當數據只包含基本類型(如字典、列表、數字、字符串等)時,應優先使用 JSON,因為 JSON 可讀性高且跨語言支持。
若數據包含複雜 Python 特定結構(如自訂類別或函數),可使用 pickle。

什麼時候不應該使用 pickle?

  • 需要跨語言操作:如果需要和非 Python 程序共享數據,應使用 JSON 或其他標準格式。
  • 需要數據長期保存:如果數據需要長期保存或存入資料庫,pickle 並不是最佳選擇,因為它受 Python 版本影響且可讀性差。

Shelve

shelve 是 Python 標準庫中一個方便的模組,
用於將 Python 物件存儲到一個類似字典的持久化對象中。
它結合了 pickle 的序列化能力和簡單的鍵值存取方式,
使得開發者可以輕鬆地保存和讀取 Python 的數據結構到文件中,
而不需要自己處理文件操作和序列化細節。

shelve 的特點

  1. 類似字典的操作方式:
    • 用法和字典類似,可以透過鍵值對儲存和讀取數據。
    • 使用時只需記住操作字典的方法,例如 db[key] = value。
  2. 自動序列化:
    • 支持將多種類型的 Python 物件(如字典、列表、自定義對象)直接保存到檔案中,底層使用 pickle 處理序列化。
  3. 持久化存儲:
    • 數據保存在硬碟文件中,程序重啟後仍能讀取。
  4. 效率較高:
    • 因為只在需要時加載數據,對於大數據集,比 JSON 或單一 pickle 文件更有效。
  5. 限制:
    • 只能使用字符串作為鍵。
    • 存儲的對象需可被 pickle 序列化。
    • 與數據庫的設計不同,適用於簡單數據存儲而非高併發操作。

基本使用範例

import shelve

# 開啟一個 shelve 檔案
with shelve.open("mydata") as db:
    # 儲存數據
    db["name"] = "Alice"
    db["age"] = 30
    db["skills"] = ["Python", "C++", "Java"]

    # 從檔案中讀取數據
    print(db["name"])  # 輸出: Alice
    print(db["age"])   # 輸出: 30
    print(db["skills"])  # 輸出: ['Python', 'C++', 'Java']
特性 Shelve Pickle JSON SQLite
儲存格式 類似字典的檔案 二進制檔案 文本檔案 數據庫檔案
可讀性
數據類型支持 任意 Python 對象 任意 Python 對象 基本數據類型 基本數據類型
操作方式 類似字典 程序控制序列化/反序列化 程序控制序列化/反序列化 SQL 操作
應用場景 小型數據持久化存儲 任意序列化需求 跨語言數據傳輸 結構化數據存儲
2個讚