python3 pickle持久化的儲存數據。
python程序運行中得到了一些字符串,列表,字典等數據,想要長久的保存下來,方便以后使用,而不是簡單的放入內存中關機斷電就丟失數據。python模塊大全中pickle模塊就排上用場了, 他可以將對象轉換為一種可以傳輸或存儲的格式。
pickle對象串行化
- pickle模塊將任意一個python對象轉換成一系統字節的這個操作過程叫做串行化對象;
pickle與cpickle比較
-
pickle完全用python來實現的,cpickle用C來實現的,cpickle的速度要比pickle快好多倍,電腦中如果有cpickle的話建議使用cpickle。
pickle模塊中常用的函數:
- pickle.dump(obj, file, [,protocol])
- 含義:pickle.dump(對象,文件,[使用協議])
- 將要持久化的數據“對象”,保存到“文件”中,使用有3種協議,索引0為ASCII,1為舊式二進制,2為新式二進制協議,不同之處在於2要更高效一些。
- 默認dump方法使用0做協議
- pickle.load(file)
- 含義:pickle.load(文件),將file中的對象序列化讀出。
- 從“文件”中讀取字符串,將他們反序列化轉換為python的數據對象,可以像操作數據類型的這些方法來操作它們;
- pickle.dumps(obj[, protocol])
- 函數的功能:將obj對象序列化為string形式,而不是存入文件中。
- obj:想要序列化的obj對象。
- protocal:如果該項省略,則默認為0。如果為負值或HIGHEST_PROTOCOL,則使用最高的協議版本。
- pickle.loads(string)
- 函數的功能:從string中讀出序列化前的obj對象。
- string:文件名稱。
dump() 與 load() 相比 dumps() 和 loads() 還有另一種能力:dump()函數能一個接一個地將幾個對象序列化存儲到同一個文件中,隨后調用load()來以同樣的順序反序列化讀出這些對象。
pickle實例代碼:
1、一個字典a,用dumple()存儲到本地文件,所存數據的格式就是字典,而普通的file.write()寫入文件的是字符串。讀取時,load()返回的是一個字典,file.read()返回的是一個字符串。
1 import pickle 2 3 4 a = {" name ": "Tom", "age": "40"} 5 with open('text.txt', 'wb') as file: 6 pickle.dump(a, file) 7 8 with open('text.txt', 'rb') as file2: 9 b = pickle.load(file2) 10 11 print(type(b)) 12 print(b)
執行結果:
/usr/bin/python3.5 /home/rxf/python3_1000/1000/python3_server/python_pickle/example.py <class 'dict'> {'age': '40', ' name ': 'Tom'}
2、一個列表info,用 pickle.dumps()方法將info序列化為string形式,而不是存入文件中。用pickle.loads()方法從string(文件名稱data1)讀出序列化前的對象。
1 import pickle 2 import pprint 3 4 info = [1, 2, 3, 'abc', 'ilovepython'] 5 print('原始數據:') 6 pprint.pprint(info) 7 8 data1 = pickle.dumps(info) 9 data2 = pickle.loads(data1) 10 11 print("序列化:%r" % data1) 12 print("反序列化: %r" % data2)
執行結果:
/usr/bin/python3.5 /home/rxf/python3_1000/1000/python3_server/python_pickle/demo1.py 原始數據: [1, 2, 3, 'abc', 'ilovepython'] 序列化:b'\x80\x03]q\x00(K\x01K\x02K\x03X\x03\x00\x00\x00abcq\x01X\x0b\x00\x00\x00ilovepythonq\x02e.' 反序列化: [1, 2, 3, 'abc', 'ilovepython'] Process finished with exit code 0
3、pickle模塊主要函數實例
1 # pickle模塊主要函數的應用舉例 2 import pickle 3 import pprint 4 5 dataList = [[8, 1, 'python'], 6 [8, 1, 'python'], 7 [8, 0, 'python'], 8 [8, 1, 'C++'], 9 [8, 1, 'C++']] 10 dataDic = {0: [1, 2, 3, 4], 11 1: ('a', 'b'), 12 2: {'c': 'yes', 'd': 'no'}} 13 print("原始數據dataList:") 14 pprint.pprint(dataList) 15 print('\n') 16 print("原始數據dataDic:") 17 pprint.pprint(dataDic) 18 19 # 使用dump()將數據序列化到文件中 20 fw = open('dataFile.txt', 'wb') 21 # Pickle the list using the highest protocol available. 22 pickle.dump(dataList, fw) 23 # Pickle dictionary using protocol 0. 24 pickle.dump(dataDic, fw) 25 fw.close() 26 27 # 使用load()將數據從文件中序列化讀出 28 fr = open('dataFile.txt', 'rb') 29 data1 = pickle.load(fr) 30 print('\n'+"反序列化1:%r" % data1) 31 data2 = pickle.load(fr) 32 print("反序列化2:%r" % data2 + '\n') 33 fr.close() 34 35 # 使用dumps()和loads()舉例 36 p = pickle.dumps(dataList) 37 print(pickle.loads(p)) 38 p = pickle.dumps(dataDic) 39 print(pickle.loads(p))
執行結果:
/usr/bin/python3.5 /home/rxf/python3_1000/1000/python3_server/python_pickle/demo2.py 原始數據dataList: [[8, 1, 'python'], [8, 1, 'python'], [8, 0, 'python'], [8, 1, 'C++'], [8, 1, 'C++']] 原始數據dataDic: {0: [1, 2, 3, 4], 1: ('a', 'b'), 2: {'c': 'yes', 'd': 'no'}} 反序列化1:[[8, 1, 'python'], [8, 1, 'python'], [8, 0, 'python'], [8, 1, 'C++'], [8, 1, 'C++']] 反序列化2:{0: [1, 2, 3, 4], 1: ('a', 'b'), 2: {'d': 'no', 'c': 'yes'}} [[8, 1, 'python'], [8, 1, 'python'], [8, 0, 'python'], [8, 1, 'C++'], [8, 1, 'C++']] {0: [1, 2, 3, 4], 1: ('a', 'b'), 2: {'d': 'no', 'c': 'yes'}} Process finished with exit code 0
4、要注意的是,在load(file)時,要讓python能夠找到類的定義,否則會報錯:
1 import pickle 2 3 4 class Person: 5 def __init__(self, name, age): 6 self.name = name 7 self.age = age 8 9 def show(self): 10 print(self.name+"_"+str(self.age)) 11 12 aa = Person("Battier", 6) 13 aa.show() 14 15 f = open('./demo3.txt', 'wb') 16 pickle.dump(aa, f, 0) 17 f.close() 18 19 # del Person 20 f = open('./demo3.txt', 'rb') 21 bb = pickle.load(f) 22 23 f.close() 24 bb.show()
如果不注釋掉del Person的話,那么會報錯:(意思就是當前的模塊找不到類了)
/usr/bin/python3.5 /home/rxf/python3_1000/1000/python3_server/python_pickle/demo3.py Battier_6 Traceback (most recent call last): File "/home/rxf/python3_1000/1000/python3_server/python_pickle/demo3.py", line 21, in <module> bb = pickle.load(f) AttributeError: Can't get attribute 'Person' on <module '__main__' from '/home/rxf/python3_1000/1000/python3_server/python_pickle/demo3.py'> Process finished with exit code 1
5、清空pickler的“備忘”,使用Pickler實例在序列化對象的時候,它會“記住”已經被序列化的對象引用,所以對同一對象多次調用dump(obj),pickler不會“傻呼呼”的去多次序列化。
1 import pickle 2 import io 3 4 5 class Person: 6 def __init__(self, name, age): 7 self.name = name 8 self.age = age 9 10 def show(self): 11 print(self.name + "_"+str(self.age)) 12 13 aa = Person("Battier", 6) 14 aa.show() 15 16 17 fle = io.BytesIO() 18 pick = pickle.Pickler(fle) 19 pick.dump(aa) 20 val1 = fle.getvalue() 21 print(len(val1)) 22 23 pick.clear_memo() 24 pick.dump(aa) 25 val2 = fle.getvalue() 26 print(len(val2)) 27 fle.close()
上面代碼運行結果:
/usr/bin/python3.5 /home/rxf/python3_1000/1000/python3_server/python_pickle/demo4.py Battier_6 69 138 Process finished with exit code 0
再注釋掉pick.clear_memo()后,運行結果如下:
/usr/bin/python3.5 /home/rxf/python3_1000/1000/python3_server/python_pickle/demo4.py Battier_6 69 74 Process finished with exit code 0
主要是因為,python的pickle如果不clear_memo,則不會多次去序列化對象。