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的陣列和實例datetime
,date
並且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()
運行結果:

