一、概述
前面章节我们讲述了json和pickle模块的序列化和反序列化处理,他们有一个不足是在python 3中不能多次dump和load,shelve模块则可以规避这个问题。
shelve模块是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式,是pickle 更上一层的封装。
二、shelve模块的用法
Shelve模块提供了基本的存储操作,Shelve中的open函数在调用的时候返回一个shelf对象,通过该对象可以存储内容,即像操作字典一样进行存储操作。当在该对象中查找元素时,对象会根据已经存储的版本进行重新构建,当给某个键赋值的时候,元素会被存储。
- 持久化存储代码执行后会生成三个文件:
1 import shelve 2 3 def member_info(name, age): 4 print("Member info:", name, age) 5 6 name = [‘Jack‘, ‘Maxwell‘, ‘Tom‘] 7 info = {‘name‘:‘Maxwell‘, ‘age‘:18} 8 9 with shelve.open(‘shelve_demo‘) as data: 10 data[‘name‘] = name 11 data[‘info‘] = info 12 data[‘func‘] = member_info
其中shelve_demo.bak和shelve_demo.dir文件内容相同,显示如下:shelve_demo.dat猜测为类数据库文件把。1 ‘name‘, (0, 43) 2 ‘info‘, (512, 45) 3 ‘func‘, (1024, 27)
- 解析文件内容
1 import shelve 2 3 def member_info(name, age): 4 print("Member info:", name, age) 5 6 with shelve.open(‘shelve_demo‘) as data: 7 print(data[‘name‘]) #这里的key与之前保存的文件内容里面的key完全对应,否则会报错 8 print(data[‘info‘]) 9 print(data[‘func‘](‘Alex‘, 22)) 10 11 #运行结果输出: 12 [‘Jack‘, ‘Maxwell‘, ‘Tom‘] 13 {‘name‘: ‘Maxwell‘, ‘age‘: 18} 14 Member info: Alex 22 15 None
- value值的修改
一般情况下,我们通过shelve来open一个对象后,只能进行一次赋值处理,赋值后不能再次更新处理。再次open打开结果也是这样:1 import shelve 2 3 def member_info(name, age): 4 print("Member info:", name, age) 5 6 name = [‘Jack‘, ‘Maxwell‘, ‘Tom‘] 7 info = {‘name‘:‘Maxwell‘, ‘age‘:18} 8 9 with shelve.open(‘shelve_demo‘) as data: 10 data[‘name‘] = name 11 data[‘info‘] = info 12 data[‘name‘].append(‘Alex‘) 13 print(data[‘name‘]) 14 15 程序输出: 16 [‘Jack‘, ‘Maxwell‘, ‘Tom‘] #第一次赋值后apend的元素并没有生效
造成上述情况的原因是:我们只是修改了shelve对象的副本,而它并木有被最终保存。此时我们除了下文要讲述的update方法外,还有以下两种方法:1 import shelve 2 3 def member_info(name, age): 4 print("Member info:", name, age) 5 6 name = [‘Jack‘, ‘Maxwell‘, ‘Tom‘] 7 info = {‘name‘:‘Maxwell‘, ‘age‘:18} 8 9 10 with shelve.open(‘shelve_demo‘) as data: 11 print(data[‘name‘])
方法一: shelve open一个对象后,先用临时变量指向对象副本,在临时变量上修改后让对象副本再次指向临时变量,从而覆盖保存对象副本。这种方法的本质是对open后的对象重新赋新值,并非在原有基础上进行update,也就是open后的对象内存指向地址发生了变化。方法二:借助open的writeback=True参数来实现,默认情况下该参数的值为False。1 import shelve 2 3 def member_info(name, age): 4 print("Member info:", name, age) 5 6 name = [‘Jack‘, ‘Maxwell‘, ‘Tom‘] 7 info = {‘name‘:‘Maxwell‘, ‘age‘:18} 8 9 with shelve.open(‘shelve_demo‘) as data: 10 data[‘name‘] = name 11 data[‘info‘] = info 12 temp = data[‘name‘] #这里的关键点在于对临时变量的使用 13 temp.append(‘Alex‘) 14 data[‘name‘] = temp 15 print(data[‘name‘]) 16 17 程序输出: 18 [‘Jack‘, ‘Maxwell‘, ‘Tom‘, ‘Alex‘]
1 import shelve 2 3 def member_info(name, age): 4 print("Member info:", name, age) 5 6 name = [‘Jack‘, ‘Maxwell‘, ‘Tom‘] 7 info = {‘name‘:‘Maxwell‘, ‘age‘:18} 8 9 with shelve.open(‘shelve_demo‘, writeback=True) as data: 10 data[‘name‘] = name 11 data[‘info‘] = info 12 data[‘name‘].append(‘Alex‘) 13 print(data[‘name‘]) 14 15 程序输出: 16 [‘Jack‘, ‘Maxwell‘, ‘Tom‘, ‘Alex‘]
- update方法
value值的更新还有一个update方法,使用起来也比较方便:重新load一下看看结果:1 import shelve 2 3 def member_info(name, age): 4 print("Member info:", name, age) 5 6 name = [‘Jack‘, ‘Maxwell‘, ‘Tom‘] 7 info = {‘name‘:‘Maxwell‘, ‘age‘:18} 8 9 with shelve.open(‘shelve_demo‘, writeback=True) as data: 10 data[‘name‘] = name 11 data[‘info‘] = info 12 data.update({‘name‘:[‘Jack‘, ‘Maxwell‘, ‘Tom‘, ‘Alex‘]}) #这里也是重新赋值 13 print(data[‘name‘]) 14 15 程序输出: 16 [‘Jack‘, ‘Maxwell‘, ‘Tom‘, ‘Alex‘]
1 import shelve 2 3 def member_info(name, age): 4 print("Member info:", name, age) 5 6 name = [‘Jack‘, ‘Maxwell‘, ‘Tom‘] 7 info = {‘name‘:‘Maxwell‘, ‘age‘:18} 8 9 10 with shelve.open(‘shelve_demo‘) as data: 11 print(data[‘name‘]) 12 13 程序输出: 14 [‘Jack‘, ‘Maxwell‘, ‘Tom‘, ‘Alex‘]
- get方法
通过shelve.open反序列化load对象到内存后,可以通过get方法来获取key对应的value:1 __author__ = ‘Maxwell‘ 2 3 import shelve 4 5 def member_info(name, age): 6 print("Member info:", name, age) 7 8 name = [‘Jack‘, ‘Maxwell‘, ‘Tom‘] 9 info = {‘name‘:‘Maxwell‘, ‘age‘:18} 10 11 12 with shelve.open(‘shelve_demo‘) as data: 13 print(data.get(‘name‘)) 14 15 程序输出: 16 [‘Jack‘, ‘Maxwell‘, ‘Tom‘, ‘Alex‘]
三、总结
shelve概念总结:
- shelve模块可以看做是pickle模块的升级版,因为shelve使用的就是pickle的序列化协议,但是shelve比pickle提供的操作方式更加简单、方便。
- shelve模块相对于其它两个模块在将Python数据持久化到本地磁盘时有一个很明显的优点就是,它允许我们可以像操作dict一样操作被序列化的数据,而不必一次性的保存或读取所有数据。
- shelve模块持久化支持更多的python数据类型
使用建议:
- 需要与外部系统交互时用json模块;
- 需要将少量、简单Python数据持久化到本地磁盘文件时可以考虑用pickle模块;
- 需要将大量Python数据持久化到本地磁盘文件或需要一些简单的类似数据库的增删改查功能时,可以考虑用shelve模块。
以上内容摘自大神博客http://www.cnblogs.com/yyds/p/6563608.html