前言:昨天刚刚学习练习了shelve模块,特此总结一下。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
一、定义
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 = raw_input('Please enter a unique ID number: ')
person = {}
person['name'] = raw_input('Please enter the name: ')
person['age'] = raw_input('Please enter the age: ')
person['phone'] = raw_input('Please enter the phone: ')
db[pid] = person
print "Store information: pid is %s, information is %s" % (pid, person)
def lookup_people(db):
pid = raw_input('Please enter the number: ')
field = raw_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 = raw_input('Please enter the number: ')
field = raw_input('What would you like to update? (name, age, phone) ')
newvalue = raw_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 = raw_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 = raw_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()
相关引用:
anydbm: http://blog.konghy.cn/2015/06/18/python-anydbm-shelve/
protocol: https://www.cnblogs.com/pzxbc/archive/2012/03/18/2404715.html
http://www.cnblogs.com/hongten/p/hongten_python_shelve.html