shelve:極其強大的序列化模塊

介紹

數據持久化,就是把數據從內存刷到磁盤上。可是要保證在讀取的時候還能恢復到原來的狀態。像pickle和json之類的持久化模塊基本上無需介紹了,這裏介紹兩個其餘不多用可是功能很強大的模塊。

dbm

'''
在一些小型程序中,不須要關係型數據庫時,能夠方便的用持久字典來存儲鍵值對,和python中的字典很是相似。並且dbm的鍵和值都必須是str或者bytes類型
'''
import dbm
 
'''
這裏第一個參數直接傳入文件名,第二個參數表示模式
常見的模式:
r:可讀,默認就是這個模式
w:可讀可寫
可是r、w,都必須確保文件已經存在,不然報錯。
 
c:可讀可寫,文件不存在時會建立
n:可讀可寫,但老是會建立一個新的文件,也就是說若是建立同名文件,那麼以前的內容都會被清空,也就是起不到追加的效果。
 
所以咱們日常的模式通常都會選擇c
 
 
第三個參數是權限,這個在windows下基本不用,是一組用八進制表示的數字,默認是0o666,都是可讀可寫不可執行
'''
db = dbm.open("store", "c")
 
# 打開文件以後,就能夠存儲值了
# 注意key和value都必須是str或者bytes類型
db["name"] = "satori"
db["age"] = "16"
db["gender"] = "f"
db["anime"] = "東方地靈殿"
 
# 關閉文件,將內容寫到磁盤上
db.close()
 
 
################################################################
# 打開文件
db = dbm.open("store", "c")
print(db.keys())  # [b'name', b'age', b'gender', b'anime']
for key in db.keys():
    print(f"key={key}, value={db[key]}")
    '''
    key=b'name', value=b'satori'
    key=b'age', value=b'16'
    key=b'gender', value=b'f'
    key=b'anime', value=b'\xe4\xb8\x9c\xe6\x96\xb9\xe5\x9c\xb0\xe7\x81\xb5\xe6\xae\xbf'
    '''

會多出來這三個文件python

shelve

'''
 
shelve和dbm比較相似,可是功能遠比dbm強大,由於它能夠持久化任意對象
'''
import shelve
 
# 參數flag默認是c,所以咱們只須要傳入文件名就能夠了,這個是自動追加在後面的
# 也就是說我寫完以後,再次打開繼續寫的話,只會追加不會清空
sh = shelve.open("shelve")
 
sh["dict"] = {"name": "satori", "age": 16}
sh["list"] = [1, 2, 3, 4]
sh["set"] = {1, 2, 3, 2}
 
# 寫完以後關閉文件,刷到內存裏面
# 關閉以後就沒法操做了
sh.close()
 
 
# 下面咱們就能夠操做數據了,下面的代碼即使寫在另外一個py文件裏面也是能夠的
sh2 = shelve.open("shelve")
print(sh2["dict"], sh2["dict"].keys())  # {'name': 'satori', 'age': 16} dict_keys(['name', 'age'])
print(sh2["list"], sum(sh2["list"]))  # [1, 2, 3, 4] 10
print(sh2["set"])  # {1, 2, 3}
sh2.close()
 
 
# 能夠看到,拿出來的就是原生的對象,能夠直接用來進行操做的。那咱們看看本身定義的類可不能夠呢?
sh3 = shelve.open("shelve")
 
 
class A:
    def __init__(self, name, age):
        self.name = name
        self.age = age
 
    @property
    def print_info(self):
        return f"my name is {self.name}, age is {self.age}"
 
 
a = A("satori", 16)
# 將這個類和類的一個實例對象存儲進去
sh3["A"] = A
sh3["a"] = a
sh3.close()
 
 
######################################
sh4 = shelve.open("shelve")
 
# sh4["A"]拿到A這個類,傳入參數,調用方法
print(sh4["A"]("mashiro", "17").print_info)  # my name is mashiro, age is 17
 
# sh4["a"]拿到a這個實例對象,直接調用方法
print(sh4["a"].print_info)  # my name is satori, age is 16
 
# 咱們發現依舊是能夠的,說明了shelve這個模塊真的很強大
# 咱們再來看一個例子
import shelve
 
sh = shelve.open("shelve")
sh["list"] = [1, 2, 3]
sh["str"] = "mashiro"
sh.close()
 
##############################
sh = shelve.open("shelve")
sh["list"].append("xxxx")
sh["str"] = "satori"
sh.close()
 
#######################
sh = shelve.open("shelve")
print(sh["list"])  # [1, 2, 3]
print(sh["str"])  # satori
'''
分析結果,第一次打開文件咱們建立兩個鍵值對
sh["list"] = [1, 2, 3]
sh["str"] = "mashiro"
 
第二次打開文件,修改了兩個鍵的值
第三次打開文件,打印。可是咱們發現sh["str"]改變了,可是sh["list"]沒有改變,這是爲何?
首先sh["str"] = "satori"很好理解,可是爲何sh["list"]沒有變?
由於=,咱們是直接賦值,將這一塊內存裏面的值給換掉,而sh["list"]咱們是作append操做,這只是在原來的基礎上進行修改
shelve默認狀況下是不會記錄,持久化對象的修改的,除非你是建立新的對象,或者是把原來的對象給換掉
若是是在原來的基礎上(可變類型),好比列表、字典,進行添加或者刪除操做,這些是不會被記錄的
因此:sh["list"]=[1, 2, 3]  sh["list"].append("xxxx")  --->sh["list"]還是[1, 2, 3]不會是[1, 2, 3, "xxx"]
由於shelve沒有記錄對象自身的修改,若是我想獲得指望的結果,一種方法是把對象總體換掉
sh["list"] = [1, 2, 3, "xxxx"],這樣等因而從新賦值,是可行的。可是有時候咱們不知道列表裏面內容,或者列表裏面的內容是一些函數、類什麼的、很差寫的話,該咋辦呢?
其實咱們在打開文件的時候,還能夠加上一個參數,叫作writeback
'''
import shelve
 
sh = shelve.open("shelve")
sh["list"] = [1, 2, 3]
sh["str"] = "mashiro"
sh.close()
 
##############################
# 若是咱們須要進行修改,那麼加上一個writeback=True就能夠了,從名字也能看出來
# 這是會將修改的內容重新寫回去
sh = shelve.open("shelve", writeback=True)
sh["list"].append("xxxx")
sh["str"] = "satori"
sh.close()
 
#######################
sh = shelve.open("shelve")
print(sh["list"])  # [1, 2, 3, 'xxxx']
print(sh["str"])  # satori
'''
能夠看到都發生改變了,可是這個參數有缺陷,就是會有額外的內存消耗。當咱們加上writeback=True的時候shelve會將咱們讀取的對象都放到一個內存緩存當中。
好比說咱們獲取了20持久化的對象,可是咱們只修改了一個,剩餘的19個只是查看並無作修改,但當咱們sh.close()的時候,會將這20個對象都寫回去
由於shelve不知道你會對哪一個對象進行修改,因而無論你是查看仍是修改,都會放到緩存當中,而後再一次性都寫回去。
這樣會形成兩點:
1.對象放到內存緩存當中,等因而從新拷貝了一份,由於咱們讀取文件已經到內存當中了,而shelve又把咱們使用的對象放當內存的另外一片空間中
2.寫入數據,咱們明明只修改了一份數據,可是它把20份都從新寫回去了,這樣會形成性能上的問題,致使效率會下降。
所以加不加這個參數,由具體狀況決定
'''

一樣也會多出來三個文件數據庫

相關文章
相關標籤/搜索