举例简单讲解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从sqlite读取并显示数据的方法
May 08 Python
python 递归遍历文件夹,并打印满足条件的文件路径实例
Aug 30 Python
kafka-python批量发送数据的实例
Dec 27 Python
Python+OpenCV采集本地摄像头的视频
Apr 25 Python
python中count函数简单用法
Jan 05 Python
Python reshape的用法及多个二维数组合并为三维数组的实例
Feb 07 Python
python使用gdal对shp读取,新建和更新的实例
Mar 10 Python
Python __slots__的使用方法
Nov 15 Python
python 爬虫请求模块requests详解
Dec 04 Python
详解Django中的FBV和CBV对比分析
Mar 01 Python
高考要来啦!用Python爬取历年高考数据并分析
Jun 03 Python
PyCharm 配置SSH和SFTP连接远程服务器
May 11 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
星际争霸任务指南——神族
2020/03/04 星际争霸
PHP 遍历XP文件夹下所有文件
2008/11/27 PHP
PHP 远程关机实现代码
2009/11/10 PHP
PHP基于GD库的缩略图生成代码(支持jpg,gif,png格式)
2014/06/19 PHP
Laravel 读取 config 下的数据方法
2019/10/13 PHP
tp5框架前台无限极导航菜单类实现方法分析
2020/03/29 PHP
Laravel框架源码解析之反射的使用详解
2020/05/14 PHP
JS图片根据鼠标滚动延时加载的实例代码
2013/07/13 Javascript
Javascript基础教程之JavaScript语法
2015/01/18 Javascript
Jquery中offset()和position()的区别分析
2015/02/05 Javascript
nodeJs爬虫获取数据简单实现代码
2016/03/29 NodeJs
Node.js环境下JavaScript实现单链表与双链表结构
2016/06/12 Javascript
JavaScript实现Fly Bird小游戏
2016/12/15 Javascript
利用JavaScript的Map提升性能的方法详解
2019/08/14 Javascript
使用JavaScript获取扫码枪扫描得到的条形码的思路代码详解
2020/06/10 Javascript
[02:08]2018年度CS GO枪械皮肤设计大赛优秀作者-完美盛典
2018/12/16 DOTA
Python中基本的日期时间处理的学习教程
2015/10/16 Python
python制作花瓣网美女图片爬虫
2015/10/28 Python
Python入门之后再看点什么好?
2018/03/05 Python
用pandas按列合并两个文件的实例
2018/04/12 Python
完美解决Pycharm无法导入包的问题 Unresolved reference
2018/05/18 Python
python实现自动发送邮件
2018/06/20 Python
Python读取excel指定列生成指定sql脚本的方法
2018/11/28 Python
Python中 Global和Nonlocal的用法详解
2020/01/20 Python
浅谈pymysql查询语句中带有in时传递参数的问题
2020/06/05 Python
python软件都是免费的吗
2020/06/18 Python
详解pytorch中squeeze()和unsqueeze()函数介绍
2020/09/03 Python
梅西百货澳大利亚:Macy’s Australia
2017/07/26 全球购物
严选全球尖货,立足香港:Bonpont宝盆
2018/07/24 全球购物
面向对象编程的优势是什么
2015/12/17 面试题
销售高级职员求职信
2013/10/29 职场文书
物流专业毕业生推荐信范文
2013/11/18 职场文书
服装厂厂长职责
2013/12/16 职场文书
片区教研活动总结
2014/07/02 职场文书
2015年“公民道德宣传日”活动方案
2015/05/06 职场文书
Python中的pprint模块
2021/11/27 Python