1. 程式人生 > >python的pickle和shelve模組

python的pickle和shelve模組

python中用於序列化的模組總結

 

 

目錄

pickle模組

shelve模組

xml模組

 

 

 

pickle模組

 

介紹

Pickle的問題和所有其他程式語言特有的序列化問題一樣,就是它只能用於Python,並且可能不同版本的Python彼此都不相容,因此,只能用Pickle儲存那些不重要的資料,不能成功地反序列化也沒關係,所以只用在資料儲存上,但是json能做資料傳輸和儲存。
優點就是支援的資料型別多,能序列化函式、類。

 

  

使用

json會把資料轉為字串
pickle會把資料轉為位元組型別的資料


四個方法
pickle.dumps()
pickle.dump()
pickle.load()
pickle.load()
四個方法的使用方法和json模組一樣
具體可以結合json模組一起學習
https://www.cnblogs.com/-wenli/p/10187130.html

 

 

#儲存資料

import pickle dic={'name':'linlin','age':18} data1 = pickle.dumps(dic) #序列化 f = open('file1','wb') #儲存 f.write(data1) f.close()

 

執行結果:

可以看到儲存到檔案的資料,我們是看不懂的,不同於json

 

 

 

#讀取資料

import pickle f = open('file1','rb') data2=f.read() data2=pickle.loads(data2)#反序列化 print(data2) key_value=data2['name'] print(key_value) f.close()

  

執行結果:

 

 

 

 

 

shelve模組

shelve類似於一個儲存持久化物件的持久化字典,即字典檔案。

使用方法也類似於字典。

shelve模組可以當成一個輕量的資料庫db,將資料以字典的型別(key,value)通過檔案持久化,模擬出簡單的db效果。

  

儲存資料

注意:shelve模組有個限制,它不支援多個應用同一時間往同一個DB(檔案)進行寫操作。

import shelve
db1 = shelve.open('file') #開啟一個檔案
db1['dic'] = {'int':12, 'float':2.5, 'string':'shelve db'} 
#這裡dic為key,key必須為字串,而值可以是python所支援的資料型別 #直接對檔案控制代碼[key]操作,就可以存入資料 db1.close()

 

且重要的是它還會直接在開啟的當前目錄生成三個檔案:
file.bak
file.dat
file.dir
其中shelve.db1.dat 儲存的就是b位元組資料型別的資料, bak和dir字尾的就可能是和資料庫相關的設計快取之類的東西。

  

 

讀取資料

注意:取出資料的時候也只需要直接用字典的操作方法獲取即可,但是如果key不存在會報錯

import shelve
f = shelve.open('file') #開啟一個檔案

#第一種方式
print(f.get('dic')['int']) #12
print(f.get('dic')['float']) #2.5
print(f.get('dic')['string']) #shelve db


#第二種方式
print(f['dic']['int'])#12
print(f['dic']['float']) #2.5

print(f['dic']['string']) #shelve db

 

 

修改資料

 

由於shelve在預設情況下是不會記錄對持久化物件(字典下的鍵的值-條目)做出修改的,
所以在shelve.open()時候需要修改預設引數writeback=True,
否則物件的條目修改不會'拷貝回寫'來進行儲存。

當試圖讓shelve去自動捕獲物件的變化時,應當在開啟shelf的時候將writeback設定為True。
而將writeback這個flag設定為True以後,shelf將會將所有從DB中讀取的物件存放到一個記憶體快取。
當close() shelf的時候,快取中所有的物件會被重新寫入DB。

 

#第一種方法
#修改鍵值
import shelve f = shelve.open('file',writeback=True) #開啟一個檔案 data=f['dic']['int'] data = 10 f.close() #這裡一定要關閉檔案,才能讀取到修改後的值 print(data) #10



#新增列表值
import shelve
list1 = ['tie', 'le', 'yu']
# 既然最終生成的檔案會是dat格式的,何不一開始就指定字尾是dat
db2 = shelve.open('shelve_db2.dat')
db2['lis'] = list1
# 檔案控制代碼是通過字典的操作方式去拿裡面的鍵值對,lis這個鍵對應的值是一個列表
db2['lis'].append('mao')
# 而此列表增加一個字串元素後再列印,感覺不出有發生增加的變化
print(type(db2['lis']), db2['lis'])
# 返回列表:['tie', 'le', 'yu']
#這裡返回的結果沒有'mao',因為沒有寫回。

 

 

#第二種方法
import shelve f = shelve.open('file') #開啟一個檔案 temp=f['dic'] #從檔案中讀取之前儲存的物件 temp['int']=12 #直接對物件進行修改 f['dic']=temp #重新儲存至字典檔案物件中 print(f['dic']) #{'int': 12, 'float': 2.5, 'string': 'shelve db'}

  

總結

第一種方法shelve會將所有從DB中讀取的物件存放到一個記憶體快取,當close() shelf的時候,快取中所有的物件會被重新寫入DB,所以一定要關閉檔案,重新讀取才能生效
 
 

  

writeback方式有優點也有缺點

優點是減少了我們出錯的概率,且讓物件的持久化對使用者更加的透明瞭
但這種方式並不是所有的情況下都需要
首先,使用writeback以後,shelf在open()的時候會增加額外的記憶體消耗
並且當DB在close()的時候會將快取中的每一個物件都寫入到DB,這也會帶來額外的等待時間
因為shelve沒有辦法知道快取中哪些物件修改了,哪些物件沒有修改,因此所有的物件都會被寫入

  

第二種方法通過中間變數實現了修改,這種屬於直接賦值和拷貝寫回無關,會生效,新值覆蓋舊值

 

所以我們一定要弄明白一件事情
從shelve的db檔案中重新再訪問一個key拿的是它的拷貝
修改此拷貝後不做拷貝寫回並不影響原來的key
但你要是直接做的操作是賦值新的值到一個key裡,那肯定就是指向原來的key,會被覆蓋的
而這種賦值覆蓋對於shelve來說這是一個正常的行為阿
和鍵中的值看起來不能被修改一事並不矛盾