python的pickle模塊

  • 2019 年 10 月 7 日
  • 筆記

版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/weixin_36670529/article/details/101013131

pickle模塊詳解

pickle模塊實現了用於序列化和反序列化Python對象結構的二進制協議。 「Pickling」是將Python對象層次結構轉換為位元組流的過程, 「unpickling」是反向操作,從而將位元組流(來自二進制文件或類似位元組的對象)轉換回對象層次結構。pickle模塊對於錯誤或惡意構造的數據是不安全的。

pickle協議和JSON(JavaScript Object Notation)的區別 :

  1. JSON是一種文本序列化格式(它輸出unicode文本,雖然大部分時間它被編碼utf-8),而pickle是二進制序列化格式;

  2. JSON是人類可讀的,而pickle則不是;

  3. JSON是可互操作的,並且在Python生態系統之外廣泛使用,而pickle是特定於Python的;

默認情況下,JSON只能表示Python內置類型的子集,而不能表示自定義類; pickle可以表示極其龐大的Python類型(其中許多是自動的,通過巧妙地使用Python的內省工具;複雜的案例可以通過實現特定的對象API來解決)。

pickle 數據格式是特定於Python的。它的優點是沒有外部標準強加的限制,例如JSON或XDR(不能代表指針共享); 但是這意味着非Python程序可能無法重建pickled Python對象。

默認情況下,pickle數據格式使用相對緊湊的二進制表示。如果您需要最佳尺寸特徵,則可以有效地壓縮數據。

模塊接口

要序列化對象層次結構,只需調用該dumps()函數即可。同樣,要對數據流進行反序列化,請調用該loads()函數。但是,如果你想要更多地控制序列化和反序列化,則可以分別創建一個Pickler或一個Unpickler對象。

pickle模塊提供以下常量:

pickle.HIGHEST_PROTOCOL

整數, 可用的最高協議版本。這個值可以作為一個被傳遞協議的價值函數 dump()dumps()以及該Pickler 構造函數。

pickle.DEFAULT_PROTOCOL

整數,用於編碼的默認協議版本。可能不到HIGHEST_PROTOCOL。目前,默認協議是3,這是為Python 3設計的新協議。

pickle模塊提供以下功能,使酸洗過程更加方便:

pickle.dump(obj,file,protocol = None,*,fix_imports = True )

將obj對象的編碼pickle編碼表示寫入到文件對象中,相當於Pickler(file,protocol).dump(obj)

可供選擇的協議參數是一個整數,指定pickler使用的協議版本,支持的協議是0到HIGHEST_PROTOCOL。如果未指定,則默認為DEFAULT_PROTOCOL。如果指定為負數,則選擇HIGHEST_PROTOCOL

文件參數必須具有接受單個位元組的參數寫方法。因此,它可以是為二進制寫入打開的磁盤文件, io.BytesIO實例或滿足此接口的任何其他自定義對象。

如果fix_imports為true且protocol小於3,則pickle將嘗試將新的Python 3名稱映射到Python 2中使用的舊模塊名稱,以便使用Python 2可讀取pickle數據流。

pickle.dumps(obj,protocol = None,*,fix_imports = True )

將對象的pickled表示作為bytes對象返回,而不是將其寫入文件。

參數protocol和fix_imports具有與in中相同的含義 dump()

pickle.load(file,*,fix_imports = True,encoding =「ASCII」,errors =「strict」 )

從打開的文件對象 文件中讀取pickle對象表示,並返回其中指定的重構對象層次結構。這相當於Unpickler(file).load()

pickle的協議版本是自動檢測的,因此不需要協議參數。超過pickle對象的表示的位元組將被忽略。

參數文件必須有兩個方法,一個採用整數參數的read()方法和一個不需要參數的readline()方法。兩種方法都應返回位元組。因此,文件可以是為二進制讀取而打開的磁盤文件,io.BytesIO對象或滿足此接口的任何其他自定義對象。

可選的關鍵字參數是fix_imports,encoding和errors,用於控制Python 2生成的pickle流的兼容性支持。如果fix_imports為true,則pickle將嘗試將舊的Python 2名稱映射到Python 3中使用的新名稱。編碼和 錯誤告訴pickle如何解碼Python 2編碼的8位字符串實例; 這些默認分別為'ASCII'和'strict'。該編碼可以是「位元組」作為位元組對象讀取這些8位串的實例。使用encoding='latin1'所需的取儲存NumPy的陣列和實例datetimedate並且time被Python 2解碼。

pickle.loads(bytes_object,*,fix_imports = True,encoding =「ASCII」,errors =「strict」 )

bytes對象讀取pickle對象層次結構並返回其中指定的重構對象層次結構。

pickle的協議版本是自動檢測的,因此不需要協議參數。超過pickle對象的表示的位元組將被忽略。

import numpy as np  import pickle  import io    if __name__ == '__main__':      path = 'test'      f = open(path, 'wb')      data = {'a':123, 'b':'ads', 'c':[[1,2],[3,4]]}      pickle.dump(data, f)      f.close()        f1 = open(path, 'rb')      data1 = pickle.load(f1)      print(data1)

對於python格式的數據集,我們就可以使用pickle進行加載了,下面與cifar10數據集為例,進行讀取和加載:

import numpy as np  import pickle  import random  import matplotlib.pyplot as plt  from PIL import Image    path1 = 'D:\tmpcifar10_datacifar-10-batches-pydata_batch_1'  path2 = 'D:\tmpcifar10_datacifar-10-batches-pydata_batch_2'  path3 = 'D:\tmpcifar10_datacifar-10-batches-pydata_batch_3'  path4 = 'D:\tmpcifar10_datacifar-10-batches-pydata_batch_4'  path5 = 'D:\tmpcifar10_datacifar-10-batches-pydata_batch_5'    path6 = 'D:\tmpcifar10_datacifar-10-batches-py\test_batch'    if __name__ == '__main__':      with open(path1, 'rb') as fo:          data = pickle.load(fo, encoding='bytes')            # print(data[b'batch_label'])          # print(data[b'labels'])          # print(data[b'data'])          # print(data[b'filenames'])            print(data[b'data'].shape)            images_batch = np.array(data[b'data'])          images = images_batch.reshape([-1, 3, 32, 32])          print(images.shape)          imgs = images[5, :, :, :].reshape([3, 32, 32])          img = np.stack((imgs[0, :, :], imgs[1, :, :], imgs[2, :, :]), 2)            print(img.shape)            plt.imshow(img)          plt.axis('off')          plt.show()

運行結果: