举例简单讲解Python中的数据存储模块shelve的用法


Posted in Python onMarch 03, 2016

shelve类似于一个key-value数据库,可以很方便的用来保存Python的内存对象,其内部使用pickle来序列化数据,简单来说,使用者可以将一个列表、字典、或者用户自定义的类实例保存到shelve中,下次需要用的时候直接取出来,就是一个Python内存对象,不需要像传统数据库一样,先取出数据,然后用这些数据重新构造一遍所需要的对象。下面是简单示例:

import shelve


def test_shelve():
  # open 返回一个Shelf类的实例
  #
  # 参数flag的取值范围:
  # 'r':只读打开
  # 'w':读写访问
  # 'c':读写访问,如果不存在则创建
  # 'n':读写访问,总是创建新的、空的数据库文件
  #
  # protocol:与pickle库一致
  # writeback:为True时,当数据发生变化会回写,不过会导致内存开销比较大
  d = shelve.open('shelve.db', flag='c', protocol=2, writeback=False)
  assert isinstance(d, shelve.Shelf)

  # 在数据库中插入一条记录
  d['abc'] = {'name': ['a', 'b']}
  d.sync()

  print d['abc']

  # writeback是False,因此对value进行修改是不起作用的
  d['abc']['x'] = 'x'
  print d['abc'] # 还是打印 {'name': ['a', 'b']}

  # 当然,直接替换key的value还是起作用的
  d['abc'] = 'xxx'
  print d['abc']

  # 还原abc的内容,为下面的测试代码做准备
  d['abc'] = {'name': ['a', 'b']}
  d.close()

  # writeback 为 True 时,对字段内容的修改会writeback到数据库中。
  d = shelve.open('shelve.db', writeback=True)

  # 上面我们已经保存了abc的内容为{'name': ['a', 'b']},打印一下看看对不对
  print d['abc']

  # 修改abc的value的部分内容
  d['abc']['xx'] = 'xxx'
  print d['abc']
  d.close()

  # 重新打开数据库,看看abc的内容是否正确writeback
  d = shelve.open('shelve.db')
  print d['abc']
  d.close()

这个有一个潜在的小问题,如下:

>>> import shelve 
>>> s = shelve.open('test.dat') 
>>> s['x'] = ['a', 'b', 'c'] 
>>> s['x'].append('d') 
>>> s['x'] 
['a', 'b', 'c']

存储的d到哪里去了呢?其实很简单,d没有写回,你把['a', 'b', 'c']存到了x,当你再次读取s['x']的时候,s['x']只是一个拷贝,而你没有将拷贝写回,所以当你再次读取s['x']的时候,它又从源中读取了一个拷贝,所以,你新修改的内容并不会出现在拷贝中,解决的办法就是,第一个是利用一个缓存的变量,如下所示

>>> temp = s['x'] 
>>> temp.append('d') 
>>> s['x'] = temp 
>>> s['x'] 
['a', 'b', 'c', 'd']

在python2.4以后有了另外的方法,就是把open方法的writeback参数的值赋为True,这样的话,你open后所有的内容都将在cache中,当你close的时候,将全部一次性写到硬盘里面。如果数据量不是很大的时候,建议这么做。

下面是一个基于shelve的简单数据库的代码

#database.py 
import sys, shelve 
 
def store_person(db): 
  """ 
  Query user for data and store it in the shelf object 
  """ 
  pid = raw_input('Enter unique ID number: ') 
  person = {} 
  person['name'] = raw_input('Enter name: ') 
  person['age'] = raw_input('Enter age: ') 
  person['phone'] = raw_input('Enter phone number: ') 
  db[pid] = person 
 
def lookup_person(db): 
  """ 
  Query user for ID and desired field, and fetch the corresponding data from 
  the shelf object 
  """ 
  pid = raw_input('Enter ID number: ') 
  field = raw_input('What would you like to know? (name, age, phone) ') 
  field = field.strip().lower() 
  print field.capitalize() + ':', \ 
    db[pid][field] 
 
def print_help(): 
  print 'The available commons are: ' 
  print 'store :Stores information about a person' 
  print 'lookup :Looks up a person from ID number' 
  print 'quit  :Save changes and exit' 
  print '?   :Print this message' 
 
def enter_command(): 
  cmd = raw_input('Enter command (? for help): ') 
  cmd = cmd.strip().lower() 
  return cmd 
 
def main(): 
  database = shelve.open('database.dat') 
  try:  
    while True: 
      cmd = enter_command() 
      if cmd == 'store': 
        store_person(database) 
      elif cmd == 'lookup': 
        lookup_person(database) 
      elif cmd == '?': 
        print_help() 
      elif cmd == 'quit': 
        return  
  finally: 
    database.close() 
if __name__ == '__main__': main()
Python 相关文章推荐
Python3实现连接SQLite数据库的方法
Aug 23 Python
Django1.7+python 2.78+pycharm配置mysql数据库教程
Nov 18 Python
Python with用法实例
Apr 14 Python
Python 获得13位unix时间戳的方法
Oct 20 Python
对numpy中二进制格式的数据存储与读取方法详解
Nov 01 Python
python 多线程将大文件分开下载后在合并的实例
Nov 09 Python
pycharm配置pyqt5-tools开发环境的方法步骤
Feb 11 Python
python代码中怎么换行
Jun 17 Python
PyTorch中Tensor的数据类型和运算的使用
Sep 03 Python
上帝为你开了一扇窗之Tkinter常用函数详解
Jun 02 Python
Python 发送SMTP邮件的简单教程
Jun 24 Python
python3实现常见的排序算法(示例代码)
Jul 04 Python
Python中的数据对象持久化存储模块pickle的使用示例
Mar 03 #Python
Python和Perl绘制中国北京跑步地图的方法
Mar 03 #Python
python套接字流重定向实例汇总
Mar 03 #Python
Python设计模式中单例模式的实现及在Tornado中的应用
Mar 02 #Python
Python使用设计模式中的责任链模式与迭代器模式的示例
Mar 02 #Python
详解Python设计模式编程中观察者模式与策略模式的运用
Mar 02 #Python
Python设计模式编程中解释器模式的简单程序示例分享
Mar 02 #Python
You might like
把77A收信机改造成收音机
2021/03/02 无线电
在Windows版的PHP中使用ADO
2006/10/09 PHP
值得分享的php+ajax实时聊天室
2016/07/20 PHP
laravel-admin 中列表筛选方法
2019/10/03 PHP
JSON 教程 json入门学习笔记
2020/09/22 Javascript
js修改原型的属性使用介绍
2014/01/26 Javascript
JS cookie中文乱码解决方法
2014/01/28 Javascript
html文本框提示效果的示例代码
2014/06/28 Javascript
javascript实现左右控制无缝滚动
2014/12/31 Javascript
JavaScript将当前时间转换成UTC标准时间的方法
2015/04/06 Javascript
Javascript进制转换实例分析
2015/05/14 Javascript
深入理解JQuery中的事件与动画
2016/05/18 Javascript
Bootstrap字体图标无法正常显示的解决方法
2016/10/08 Javascript
如何使用Bootstrap创建表单
2017/03/29 Javascript
JS解决移动web开发手机输入框弹出的问题
2017/03/31 Javascript
vue中使用ueditor富文本编辑器
2018/02/08 Javascript
解决layui 复选框等内置控件不显示的问题
2018/08/14 Javascript
vue使用websocket的方法实例分析
2019/06/22 Javascript
jQuery操作动画完整实例分析
2020/01/10 jQuery
详解JavaScript中的数据类型,以及检测数据类型的方法
2020/09/17 Javascript
python中xrange和range的区别
2014/05/13 Python
python 读写txt文件 json文件的实现方法
2016/10/22 Python
python实现输入数字的连续加减方法
2018/06/22 Python
用Cython加速Python到“起飞”(推荐)
2019/08/01 Python
python cv2读取rtsp实时码流按时生成连续视频文件方式
2019/12/25 Python
Python pathlib模块使用方法及实例解析
2020/10/05 Python
南威尔士家居商店:Leekes
2016/10/25 全球购物
大专自我鉴定范文
2013/10/01 职场文书
培训主管的岗位职责
2013/11/23 职场文书
测绘工程个人的自我评价
2013/11/23 职场文书
财务会计实习报告体会
2013/12/20 职场文书
计算机相关的自我评价
2014/01/15 职场文书
单位工作证明书格式
2014/10/04 职场文书
教师党员学习十八届四中全会思想汇报
2014/11/03 职场文书
2015年小学中秋节活动总结
2015/03/23 职场文书
如何在Python项目中引入日志
2021/05/31 Python