一、定義
Shelve是對象持久化保存方法,將對象保存到文件里面,缺省(即默認)的數據存儲文件是二進制的。
二、用途
可以作為一個簡單的數據存儲方案。
三、用法
使用時,只需要使用open函數獲取一個shelf對象,然后對數據進行增刪改查操作,在完成工作、並且將內存存儲到磁盤中,最后調用close函數變回將數據寫入文件。
四、關聯模塊Anydbm
相同點:
1.anydbm, shelve 都是對象持久化保存方法,將對象保存到文件里面,缺省的數據存儲文件是二進制的。這兩個模塊允許我們將一個磁盤上的文件與一個”dict-like”對象(類字典對象)關聯起來,操作這個“dict-like”對象,就像操作dict對象一項,最后可以將“dict-like”的數據持久化到文件。
2.都可以使用open函數。
區別:
anydbm的key和value的類型必須都是字符串,而shelve的key要求必須是字符串,value則可以是任意合法的python數據類型。
五、方法
1.shelve.open(filename, flag=’c’, protocol=None, writeback=False):創建或打開一個shelve對象。shelve默認打開方式支持同時讀寫操作。
filename是關聯的文件路徑。
可選參數flag,默認為‘c’,如果數據文件不存在,就創建,允許讀寫;可以是: ‘r’: 只讀;’w’: 可讀寫; ‘n’: 每次調用open()都重新創建一個空的文件,可讀寫。
protocol:是序列化模式,默認值為None。具體還沒有嘗試過,從pickle的資料中查到以下信息【protocol的值可以是1或2,表示以二進制的形式序列化】
2.shelve.close()
同步並關閉shelve對象。
注意:每次使用完畢,都必須確保shelve對象被安全關閉。同樣可以使用with語句
with shelve.open('spam') as db: db['eggs'] = 'eggs'
六、writeback參數
writeback:默認為False。當設置為True以后,shelf將會將所有從DB中讀取的對象存放到一個內存緩存。當我們close()打開的shelf的時候,緩存中所有的對象會被重新寫入DB。
writeback方式有優點也有缺點。
優點是減少了我們出錯的概率,並且讓對象的持久化對用戶更加的透明了;但這種方式並不是所有的情況下都需要,首先,使用writeback以后,shelf在open()的時候會增加額外的內存消耗,並且當DB在close()的時候會將緩存中的每一個對象都寫入到DB,這也會帶來額外的等待時間。因為shelve沒有辦法知道緩存中哪些對象修改了,哪些對象沒有修改,因此所有的對象都會被寫入。
注意:為了保存增、刪、改的內容,建議顯示的標明writeback=True。
# 七、代碼示例 # 1.創建一個shelf對象,直接使用open函數即可 import shelve s = shelve.open('test_shelf.db') # try: s['kk'] = {'int': 10, 'float': 9.5, 'String': 'Sample data'} s['MM'] = [1, 2, 3] finally: s.close() # 2.如果想要再次訪問這個shelf,只需要再次shelve.open()就可以了,然后我們可以像使用字典一樣來使用這個shelf import shelve try: s = shelve.open('test_shelf.db') value = s['kk'] print(value) finally: s.close() # 3.對shelf對象,增、刪、改操作 import shelve s = shelve.open('test_shelf.db', flag='w', writeback=True) try: # 增加 s['QQQ'] = 2333 # 刪除 del s['MM'] # 修改 s['kk'] = {'String': 'day day up'} finally: s.close() # 注意:flag設置為‘r’-只讀模式,當程序試圖去修改一個以只讀方式打開的DB時,將會拋一個訪問錯誤的異常。異常的具體類型取決於anydbm這個模塊在創建DB時所選用的DB。異常舉例:anydbm.error: need ‘c’ or ‘n’ flag to open new db # 4.循環遍歷shelf對象 import shelve s = shelve.open('test_shelf.db') try: # 方法一: for item in s.items(): print ('鍵[{}] = 值[{}]'.format(item[0], s[item[0]])) # 方法二: for key, value in s.items(): print(key, value) finally: s.close() # 5.備注一個錯誤: # open中的參數filename,起初認為需要手動新建一個.db,或者.dat的文件,目前電腦中無任何真正的數據庫文件,所以采用了新建txt文件,修改后綴的方法創建.db,或者.dat的文件。 # 解釋器報錯,提示內容為:"anydbm.error: db type could not be determined", # 原因是是filename已經存在,並且格式與shelve不符,所以提示 “db type could not be determined”。 # 解決方法是,刪除該文件。首次運行后會自動生成該filename文件。 # 6.稍微復雜些的案例,實現一個簡單提問式的數據庫 # encoding:utf-8 # 2018/3/8 # 簡單的數據庫 import sys,shelve def print_help(): '存儲(增加)、查找、更新(修改)、循環打印、刪除、退出、幫助' print('The available commons are: ') print('store : Stores information about a person') print('lookup : Looks up a person from ID numbers') print("update : Update a person's information from ID number") print('print_all: Print all informations') print("delete : Delete a person's information from ID number") print('quit : Save changes and exit') print('? : Print this message') def store_people(db): pid = input('Please enter a unique ID number: ') person = {} person['name'] = input('Please enter the name: ') person['age'] = input('Please enter the age: ') person['phone'] = input('Please enter the phone: ') db[pid] = person print("Store information: pid is %s, information is %s" % (pid, person)) def lookup_people(db): pid = input('Please enter the number: ') field = input('What would you like to know? (name, age, phone) ') if pid in db.keys(): value = db[pid][field] print("Pid %s's %s is %s" % (pid, field, value)) else: print('Not found this number') def update_people(db): pid = input('Please enter the number: ') field = input('What would you like to update? (name, age, phone) ') newvalue = input('Enter the new information: ') if pid in db.keys(): value = db[pid] value[field] = newvalue print("Pid %s's %s update information is %s" % (pid, field, newvalue)) else: print("Not found this number, can't update") def delete_people(db): pid = input('Please enter the number: ') if pid in db.keys(): del db[pid] print("pid %s's information delete done" % pid) else: print( "Not found this number, can't delete") def print_all_people(db): print( 'All information are: ') for key, value in db.items(): print(key, value) def enter_cmd(): cmd = input('Please enter the cmd(? for help): ') cmd = cmd.strip().lower() return cmd def main(): database = shelve.open('database201803.dat', writeback=True) try: while True: cmd = enter_cmd() if cmd == 'store': store_people(database) elif cmd == 'lookup': lookup_people(database) elif cmd == 'update': update_people(database) elif cmd == 'print_all': print_all_people(database) elif cmd == 'delete': delete_people(database) elif cmd == '?': print_help() elif cmd == 'quit': return finally: database.close() if __name__ == '__main__': main()
# shelve模塊比pickle模塊簡單,只有一個open函數,返回類似字典的對象,可讀可寫; # key必須為字符串,而值可以是python所支持的數據類型 # shelve模塊(**)------可以當做數據庫用,以后基本不會用,(可以很方面的往文件中寫數據類型和讀) import shelve #存取很方便(可以做一個簡單的數據存儲方案) f=shelve.open(r'sheve.txt') f['stu1_info']={'name':'egon','age':18,'hobby':['piao','smoking','drinking']} #存 f['stu2_info']={'name':'gangdan','age':53} f['school_info']={'website':'http://www.pypy.org','city':'beijing'} print(f['stu1_info']['hobby']) f.close() import shelve d=shelve.open(r'a.txt') #生成三個文件分別是:a.txt.bak\a.txt.dat\a.txt.dir d['tom']={'age':18,'sex':'male'} #存的時候會生成三個文件,不用管,是python的一種處理機制 print(d['tom']['sex']) #可以取出字典中的key對應的value print(d['tom']) #取出tom對應的字典 d.close() import shelve d=shelve.open(r'a.txt',writeback=True) #writeback=True,對子字典修改完后要寫回,否則不會看到修改后的結果 d['egon']={'age':18,'sex':'male'} #存的時候會生成三個文件,不用管,是python的一種處理機制 d['egon']['age']=20 #將年齡修改為20 print(d['egon']['age']) #此時拿到的是修改后的年齡 print(d['egon']['sex']) d.close()