举例简单讲解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 相关文章推荐
Python2.x版本中cmp()方法的使用教程
May 14 Python
python 爬取微信文章
Jan 30 Python
使用C#配合ArcGIS Engine进行地理信息系统开发
Feb 19 Python
Python爬取网易云音乐上评论火爆的歌曲
Jan 19 Python
python多进程实现进程间通信实例
Nov 24 Python
解决python 无法加载downsample模型的问题
Oct 25 Python
python3使用matplotlib绘制条形图
Mar 25 Python
python递归调用中的坑:打印有值, 返回却None
Mar 16 Python
Django后端分离 使用element-ui文件上传方式
Jul 12 Python
基于Python爬取搜狐证券股票过程解析
Nov 18 Python
python解决12306登录验证码的实现
Apr 18 Python
python可视化大屏库big_screen示例详解
Nov 23 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
php下将图片以二进制存入mysql数据库中并显示的实现代码
2010/05/27 PHP
php递归使用示例(php递归函数)
2014/02/14 PHP
PHP将回调函数作用到给定数组单元的方法
2014/08/19 PHP
php结合ACCESS的跨库查询功能
2015/06/12 PHP
php实现学生管理系统
2020/03/21 PHP
php加密解密字符串示例
2016/10/13 PHP
php微信高级接口调用方法(自定义菜单接口、客服接口、二维码)
2016/11/28 PHP
javascript的trim,ltrim,rtrim自定义函数
2008/09/21 Javascript
Extjs显示从数据库取出时间转换JSON后的出现问题
2012/11/20 Javascript
js事件冒泡实例分享(已测试)
2013/04/23 Javascript
javascript实现yield的方法
2013/11/06 Javascript
js去除空格的12种实用方法
2013/11/08 Javascript
Jquery $when done then的用法详解
2016/05/20 Javascript
AngularJS中过滤器的使用与自定义实例代码
2016/09/17 Javascript
Angular2学习笔记——详解路由器模型(Router)
2016/12/02 Javascript
微信小程序分页加载的实例代码
2017/07/11 Javascript
JavaScript事件处理程序详解
2017/09/19 Javascript
如何从0开始用node写一个自己的命令行程序
2018/12/29 Javascript
layui输入框中只允许输入整数的实现方法
2019/09/18 Javascript
深入学习Python中的装饰器使用
2016/06/20 Python
python使用opencv按一定间隔截取视频帧
2018/03/06 Python
linux下python使用sendmail发送邮件
2018/05/22 Python
Python实现字典(dict)的迭代操作示例
2018/06/05 Python
python 用所有标点符号分隔句子的示例
2019/07/15 Python
关于PyTorch源码解读之torchvision.models
2019/08/17 Python
CSS3 圆角效果
2009/07/15 HTML / CSS
HTML中fieldset标签概述及使用方法
2013/02/01 HTML / CSS
HTC VIVE美国官网:VR虚拟现实眼镜
2018/02/13 全球购物
日本即尚网:JSHOPPERS.com(支持中文)
2019/12/03 全球购物
Wiggle澳大利亚:自行车、跑步、游泳商店
2020/11/07 全球购物
机电工程学生自荐信范文
2013/12/07 职场文书
收银员的岗位职责范本
2014/02/04 职场文书
2015安全保卫工作总结
2015/04/25 职场文书
python 遍历磁盘目录的三种方法
2021/04/02 Python
Python 读写 Matlab Mat 格式数据的操作
2021/05/19 Python
深入浅析Django MTV模式
2021/09/04 Python