举例简单讲解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 相关文章推荐
python类装饰器用法实例
Jun 04 Python
Python访问纯真IP数据库脚本分享
Jun 29 Python
pytorch cnn 识别手写的字实现自建图片数据
May 20 Python
python 杀死自身进程的实现方法
Jul 01 Python
关于Flask项目无法使用公网IP访问的解决方式
Nov 19 Python
快速解决jupyter notebook启动需要密码的问题
Apr 21 Python
python+requests接口压力测试500次,查看响应时间的实例
Apr 30 Python
python中round函数如何使用
Jun 19 Python
Python3.7安装pyaudio教程解析
Jul 24 Python
python 高阶函数简单介绍
Feb 19 Python
Django实现简单的分页功能
Feb 22 Python
Django debug为True时,css加载失败的解决方案
Apr 24 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中数组的分组排序实例
2014/06/01 PHP
ThinkPHP采用实现三级循环代码实例
2014/07/18 PHP
thinkPHP分页功能实例详解
2017/05/05 PHP
php中各种定义变量的方法小结
2017/10/18 PHP
File, FileReader 和 Ajax 文件上传实例分析(php)
2011/04/27 Javascript
Javascript学习指南
2014/12/01 Javascript
javascript中Function类型详解
2015/04/28 Javascript
JavaScript函数使用的基本教程
2015/06/04 Javascript
jquery实现简单的二级导航下拉菜单效果
2015/09/07 Javascript
jQuery插件实现适用于移动端的地址选择器
2016/02/18 Javascript
详解AngularJS控制器的使用
2016/03/09 Javascript
TinyMCE汉化及本地上传图片功能实例详解
2016/05/31 Javascript
jQuery查看选中对象HTML代码的方法
2016/06/17 Javascript
JavaScript正则获取地址栏中参数的方法
2017/03/02 Javascript
简单谈谈require模块化jquery和angular的问题
2017/06/23 jQuery
js实现网页的两个input标签内的数值加减(示例代码)
2017/08/15 Javascript
你应该知道的几类npm依赖包管理详解
2017/10/06 Javascript
OpenLayers3实现图层控件功能
2020/09/25 Javascript
vue动态合并单元格并添加小计合计功能示例
2020/11/26 Vue.js
python实现批量转换文件编码(批转换编码示例)
2014/01/23 Python
Python中多线程及程序锁浅析
2015/01/21 Python
pandas.loc 选取指定列进行操作的实例
2018/05/18 Python
Python用5行代码写一个自定义简单二维码
2018/10/21 Python
pytorch GAN伪造手写体mnist数据集方式
2020/01/10 Python
python利用datetime模块计算程序运行时间问题
2020/02/20 Python
利用python在excel中画图的实现方法
2020/03/17 Python
Django自关联实现多级联动查询实例
2020/05/19 Python
Groupon西班牙官方网站:在线优惠券和交易,节省高达70%
2021/03/13 全球购物
网络工程师面试(三木通信技术有限公司)
2013/06/05 面试题
有针对性的求职自荐信
2013/11/14 职场文书
客服专员岗位职责范本
2013/11/29 职场文书
市场营销专业毕业生求职信
2014/03/26 职场文书
教师对学生的评语
2014/04/28 职场文书
送温暖献爱心活动总结
2014/07/08 职场文书
公司授权委托书范文
2014/09/21 职场文书
解决SpringBoot文件上传临时目录找不到的问题
2021/07/01 Java/Android