數據持久化,就是把數據從內存刷到磁盤上。可是要保證在讀取的時候還能恢復到原來的狀態。像pickle和json之類的持久化模塊基本上無需介紹了,這裏介紹兩個其餘不多用可是功能很強大的模塊。
''' 在一些小型程序中,不須要關係型數據庫時,能夠方便的用持久字典來存儲鍵值對,和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和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份都從新寫回去了,這樣會形成性能上的問題,致使效率會下降。 所以加不加這個參數,由具體狀況決定 '''
一樣也會多出來三個文件
數據庫