2023-09-04|閱讀時間 ‧ 約 10 分鐘

Python 的序列化套件-JSON與Pickle

序列化(serialization)是將資料結構或對象轉換為一個格式,可以被儲存到文件或記憶體中,或者可以透過網路傳輸到另一個系統環境。這使得資料可以在不同的系統之間進行交換,並在需要時重新建構回原始的資料結構。本文將介紹兩個好用的Python套件-JSON與Pickle,並比較兩者的不同。

JSON

JSON(Javascript Object Notation)是一種輕量級的資料交換格式。它基於 JavaScript 語言,但是獨立於語言和平台。JSON 易於人閱讀和寫作,同時也易於機器解析和生成。

在使用JSON套件時,需要先引入該套件:

import json

將資料結構轉換為字串

json.dumps(obj, skipkeys: bool, ensure_ascii: bool, indent: int) -> str
  • obj: 要序列化的 Python 對象。
  • skipkeys: 默認為 False。如果設為 True,則字典的鍵不是基本類型 (str, int, float, bool, None) 會被跳過,而不是引發 TypeError
  • ensure_ascii: 默認為 True。如果設為 True,所有非 ASCII 字符都會被轉義。
  • indent: 指定縮進的空格數,用於美化輸出。

例如,以下程式碼將字典 data 轉為字串 json_string

import json

data = {
    "name": "John",
    "age": 30,
    "city": "New York"
}
json_string = json.dumps(obj = data, indent = 4)
print(json_string)
print(type(json_string))
{
"name": "John",
"age": 30,
"city": "New York"
}
<class 'str'>

將資料結構寫入以字串的形式寫入檔案

將資料結構轉換成字串後,我們便可以將它寫入文字檔儲存,不過JSON套件已有函式可將資料結構以文本形式儲存到檔案,如下:

json.dump(obj, fp, skipkeys: bool, ensure_ascii: bool, indent: int)
  • fp: 一個 .write() 支持的文本文件對象。
  • 其餘參數與 json.dumps()相同

data寫入data.json:

import json

data = {
    "name": "John",
    "age": 30,
    "city": "New York"
}

with open('data.json', 'w', encoding = 'utf8') as file:
    json.dump(fp = file, obj = data, ensure_ascii = False, indent = 4)

data.json文件內容:

{
    "name": "John",
    "age": 30,
    "city": "New York"
}

將字串轉換為資料結構

json.loads(s)
  • s:要解碼的JSON字符串。

json_data轉為字典存入 data

import json

json_data = '{"name": "John", "age": 30, "city": "New York"}'
data = json.loads(json_data)
print(f"name: {data['name']}")
print(f"age: {data['age']}")
print(f"city: {data['city']}")
print(type(data))
name: John
age: 30
city: New York
<class 'dict'>

讀取檔案並將其寫入資料結構

json.load(fp)
  • fp:一個 .read() 支持的文本文件對象。

例如讀取data.json並存入data中:

import json

with open('data.json', 'r', encoding = 'utf8') as file:
    data = json.load(file)

print(f"name: {data['name']}")
print(f"age: {data['age']}")
print(f"city: {data['city']}")
print(type(data))
name: John
age: 30
city: New York
<class 'dict'>

Pickle

Pickle 是 Python 的一個標準模組,用於序列化和反序列化 Python 對象結構。它可以序列化許多 Python 的資料類型,包括自定義的類。

在使用Pickle套件時,需要先引入該套件:

import pickle

將資料結構輸出為檔案

pickle.dump(obj, file, protocol, fix_imports)
  • obj: 要序列化的 Python 對象。
  • file: 一個 .write() 支持的二進制文件對象。
  • protocol: 指定使用的 pickling 協議。默認為 pickle.DEFAULT_PROTOCOL。可選的協議版本為 0, 1, 2, 3, 4。
    • 0: ASCII 協議,可讀性強,但效率較低。
    • 1: 舊的二進制協議。
    • 2: 在 Python 2.3 中引入的協議。
    • 3: 在 Python 3.0 中引入的協議,不兼容 Python 2。
    • 4: 在 Python 3.4 中引入,支持大於 4GB 的對象。
  • fix_imports: 默認為 True。如果為 Trueprotocol 小於 3,將修改 pickle 輸出,使其可以在 Python 2 中讀取。

例如將data輸出為data.obj:

import pickle
data = {
    "name": "John",
    "age": 30,
    "city": "New York"
}

with open('data.obj', 'wb') as file:
    pickle.dump(data, file)

會產生一個data.obj的二進位檔。

將檔案轉化為資料結構

pickle.load(file, fix_imports, encoding, errors)
  • file: 一個 .read() 支持的二進制文件對象。
  • fix_imports: 默認為 True。用於控制對 Python 2 中生成的 pickle 數據的導入修復。
  • encoding: 默認為 'ASCII'。用於解碼 Python 2 中的 Unicode 字符串。其他常見的值包括 'latin1''utf8'
  • errors: 默認為 'strict'。指定如何處理解碼錯誤。其他可能的值包括 'replace''ignore'

例如讀取剛剛產生的data.obj:

import pickle

with open('data.obj', 'rb') as file:
    data = pickle.load(file)

print(f"name: {data['name']}")
print(f"age: {data['age']}")
print(f"city: {data['city']}")
print(type(data))
name: John
age: 30
city: New York
<class 'dict'>

JSON與Pickle的差異

  1. 資料格式:Json 產生的是文本格式,而 Pickle 產生的是字節流。
  2. 兼容性:Json 是一種跨語言的資料格式,而 Pickle 是 Python 專用的。
  3. 資料類型:Json 支持的資料類型較少,而 Pickle 可以序列化許多 Python 的資料類型。
    例如以下我們自定義一個class Data,有屬性nameagecity,以及一個建構子來初始化這三個屬性,並將它儲存至data.obj:
import pickle

class Data:
    def __init__(self, name, age, city):
        self.name = name
        self.age = age
        self.city = city

data = Data('John', 30, 'New York')

with open('data.obj', 'wb') as file:
    pickle.dump(data, file)

會產生一個data.obj的二進為檔,我們讀取他並存於 new_data

import pickle

class Data:
    def __init__(self, name, age, city):
        self.name = name
        self.age = age
        self.city = city

with open('data.obj', 'rb') as file:
    data = pickle.load(file)

print(f"name: {data.name}")
print(f"age: {data.age}")
print(f"city: {data.city}")
print(type(data)
name: John
age: 30
city: New York
<class '__main__.Data'>

以上就是Python的序列化套件介紹,在之後的深度學習也會很常用到這兩個套件,感謝各位的閱讀!

分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.