shelve 用来持久化任意的Python对象实例代码
shelve--用来持久化任意的Python对象
这几天接触了Python中的shelve这个module,感觉比pickle用起来更简单一些,它也是一个用来持久化Python对象的简单工具。当我们写程序的时候如果不想用关系数据库那么重量级的东东去存储数据,不妨可以试试用shelve。shelf也是用key来访问的,使用起来和字典类似。shelve其实用anydbm去创建DB并且管理持久化对象的。
创建一个新的shelf
直接使用shelve.open()就可以创建了
importshelve s=shelve.open('test_shelf.db') try: s['key1']={'int':10,'float':9.5,'string':'Sampledata'} finally: s.close()
如果想要再次访问这个shelf,只需要再次shelve.open()就可以了,然后我们可以像使用字典一样来使用这个shelf
importshelve s=shelve.open('test_shelf.db') try: existing=s['key1'] finally: s.close() printexisting
当我们运行以上两个py,我们将得到如下输出:
$pythonshelve_create.py $pythonshelve_existing.py {'int':10,'float':9.5,'string':'Sampledata'}
dbm这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB:
importshelve s=shelve.open('test_shelf.db',flag='r') try: existing=s['key1'] finally: s.close() printexisting
当我们的程序试图去修改一个以只读方式打开的DB时,将会抛一个访问错误的异常。异常的具体类型取决于anydbm这个模块在创建DB时所选用的DB。
写回(Write-back)
由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。
importshelve s=shelve.open('test_shelf.db') try: prints['key1'] s['key1']['new_value']='thiswasnotherebefore' finally: s.close() s=shelve.open('test_shelf.db',writeback=True) try: prints['key1'] finally: s.close()
上面这个例子中,由于一开始我们使用了缺省参数shelve.open()了,因此第6行修改的值即使我们s.close()也不会被保存。
执行结果如下:
$pythonshelve_create.py $pythonshelve_withoutwriteback.py {'int':10,'float':9.5,'string':'Sampledata'} {'int':10,'float':9.5,'string':'Sampledata'}
所以当我们试图让shelve去自动捕获对象的变化,我们应该在打开shelf的时候将writeback设置为True。当我们将writeback这个flag设置为True以后,shelf将会将所有从DB中读取的对象存放到一个内存缓存。当我们close()打开的shelf的时候,缓存中所有的对象会被重新写入DB。
importshelve s=shelve.open('test_shelf.db',writeback=True) try: prints['key1'] s['key1']['new_value']='thiswasnotherebefore' prints['key1'] finally: s.close() s=shelve.open('test_shelf.db',writeback=True) try: prints['key1'] finally: s.close()
writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。
$pythonshelve_create.py $pythonshelve_writeback.py {'int':10,'float':9.5,'string':'Sampledata'} {'int':10,'new_value':'thiswasnotherebefore','float':9.5,'string':'Sampledata'} {'int':10,'new_value':'thiswasnotherebefore','float':9.5,'string':'Sampledata'}
最后再来个复杂一点的例子:
#!/bin/envpython importtime importdatetime importmd5 importshelve LOGIN_TIME_OUT=60 db=shelve.open('user_shelve.db',writeback=True) defnewuser(): globaldb prompt="logindesired:" whileTrue: name=raw_input(prompt) ifnameindb: prompt="nametaken,tryanother:" continue eliflen(name)==0: prompt="nameshouldnotbeempty,tryanother:" continue else: break pwd=raw_input("password:") db[name]={"password":md5_digest(pwd),"last_login_time":time.time()} #print'-->',db defolduser(): globaldb name=raw_input("login:") pwd=raw_input("password:") try: password=db.get(name).get('password') exceptAttributeError,e: print"\033[1;31;40mUsername'%s'doesn'texisted\033[0m"%name return ifmd5_digest(pwd)==password: login_time=time.time() last_login_time=db.get(name).get('last_login_time') iflogin_time-last_login_time<LOGIN_TIME_OUT: print"\033[1;31;40mYoualreadyloggedinat:<%s>\033[0m"%datetime.datetime.fromtimestamp(last_login_time).isoformat() db[name]['last_login_time']=login_time print"\033[1;32;40mwelcomeback\033[0m",name else: print"\033[1;31;40mloginincorrect\033[0m" defmd5_digest(plain_pass): returnmd5.new(plain_pass).hexdigest() defshowmenu(): #print'>>>',db globaldb prompt=""" (N)ewUserLogin (E)xistingUserLogin (Q)uit Enterchoice:""" done=False whilenotdone: chosen=False whilenotchosen: try: choice=raw_input(prompt).strip()[0].lower() except(EOFError,KeyboardInterrupt): choice="q" print"\nYoupicked:[%s]"%choice ifchoicenotin"neq": print"invalidoption,tryagain" else: chosen=True ifchoice=="q":done=True ifchoice=="n":newuser() ifchoice=="e":olduser() db.close() if__name__=="__main__": showmenu()
感谢阅读本文,希望能帮助到大家,谢谢大家对本站的支持!