举例简单讲解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 相关文章推荐
tornado 多进程模式解析
Jan 15 Python
python 读文件,然后转化为矩阵的实例
Apr 23 Python
python读取图片并修改格式与大小的方法
Jul 24 Python
详解python中的Turtle函数库
Nov 19 Python
Python提取支付宝和微信支付二维码的示例代码
Feb 15 Python
python+mysql实现教务管理系统
Feb 20 Python
python实现复制大量文件功能
Aug 31 Python
python动态文本进度条的实例代码
Jan 22 Python
python实现可下载音乐的音乐播放器
Feb 25 Python
python 追踪except信息方式
Apr 25 Python
pytorch 移动端部署之helloworld的使用
Oct 30 Python
教你如何使用Python实现二叉树结构及三种遍历
Jun 18 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 header下载函数
2014/01/31 PHP
ThinkPHP多表联合查询的常用方法
2020/03/24 PHP
最新制作ThinkPHP3.2.3完全开发手册
2015/11/23 PHP
PHP实现JS中escape与unescape的方法
2016/07/11 PHP
php禁用cookie后session设置方法分析
2016/10/19 PHP
php实现批量上传数据到数据库(.csv格式)的案例
2017/06/18 PHP
基于jQuery的的一个隔行变色,鼠标移动变色的小插件
2010/07/06 Javascript
js当一个变量为函数时 应该注意的一点细节小结
2011/12/29 Javascript
javaScript复制功能调用实现方案
2012/12/13 Javascript
js 左右悬浮对联广告特效代码
2014/12/12 Javascript
使用C++为node.js写扩展模块
2015/04/22 Javascript
基于javascript实现listbox左右移动
2016/01/29 Javascript
[原创]Javascript 实现广告后加载 可加载百度谷歌联盟广告
2016/05/11 Javascript
JavaScript实现复制或剪切内容到剪贴板功能的方法
2016/05/23 Javascript
JS中innerHTML和pasteHTML的区别实例分析
2016/06/22 Javascript
微信小程序 连续旋转动画(this.animation.rotate)详解
2017/04/07 Javascript
vue+element加入签名效果(移动端可用)
2019/06/17 Javascript
layui之table checkbox初始化时选中对应选项的方法
2019/09/02 Javascript
Python 异常处理实例详解
2014/03/12 Python
利用Python批量生成任意尺寸的图片
2016/08/29 Python
python使用for循环计算0-100的整数的和方法
2019/02/01 Python
python根据文章标题内容自动生成摘要的实例
2019/02/21 Python
python__new__内置静态方法使用解析
2020/01/07 Python
使用Tensorflow实现可视化中间层和卷积层
2020/01/24 Python
python属于哪种语言
2020/08/16 Python
解决Ubuntu18中的pycharm不能调用tensorflow-gpu的问题
2020/09/17 Python
pandas将list数据拆分成行或列的实现
2020/12/13 Python
CSS3实现文字波浪线效果示例代码
2016/11/20 HTML / CSS
美国咖啡批发网站:Coffee.org
2017/06/29 全球购物
FILA德国官方网站:来自意大利的体育和街头服饰品牌
2019/07/19 全球购物
致标枪运动员广播稿
2014/02/06 职场文书
《童年》教学反思
2014/02/18 职场文书
团组织推荐意见
2015/06/05 职场文书
golang在GRPC中设置client的超时时间
2021/04/27 Golang
PyTorch 如何自动计算梯度
2021/05/23 Python
微前端qiankun改造日渐庞大的项目教程
2022/06/21 Javascript