shelve  用来持久化任意的Python对象实例代码


Posted in Python onOctober 12, 2016

shelve -- 用来持久化任意的Python对象

这几天接触了Python中的shelve这个module,感觉比pickle用起来更简单一些,它也是一个用来持久化Python对象的简单工具。当我们写程序的时候如果不想用关系数据库那么重量级的东东去存储数据,不妨可以试试用shelve。shelf也是用key来访问的,使用起来和字典类似。shelve其实用anydbm去创建DB并且管理持久化对象的。

 创建一个新的shelf

直接使用shelve.open()就可以创建了

import shelve

s = shelve.open('test_shelf.db')
try:
  s['key1'] = { 'int': 10, 'float':9.5, 'string':'Sample data' }
finally:
  s.close()

如果想要再次访问这个shelf,只需要再次shelve.open()就可以了,然后我们可以像使用字典一样来使用这个shelf

import shelve

s = shelve.open('test_shelf.db')
try:
  existing = s['key1']
finally:
  s.close()

print existing

当我们运行以上两个py,我们将得到如下输出:

$ python shelve_create.py
$ python shelve_existing.py

{'int': 10, 'float': 9.5, 'string': 'Sample data'}

dbm这个模块有个限制,它不支持多个应用同一时间往同一个DB进行写操作。所以当我们知道我们的应用如果只进行读操作,我们可以让shelve通过只读方式打开DB:

import shelve

s = shelve.open('test_shelf.db', flag='r')
try:
  existing = s['key1']
finally:
  s.close()

print existing

当我们的程序试图去修改一个以只读方式打开的DB时,将会抛一个访问错误的异常。异常的具体类型取决于anydbm这个模块在创建DB时所选用的DB。

写回(Write-back)

由于shelve在默认情况下是不会记录待持久化对象的任何修改的,所以我们在shelve.open()时候需要修改默认参数,否则对象的修改不会保存。

import shelve

s = shelve.open('test_shelf.db')
try:
  print s['key1']
  s['key1']['new_value'] = 'this was not here before'
finally:
  s.close()

s = shelve.open('test_shelf.db', writeback=True)
try:
  print s['key1']
finally:
  s.close()

上面这个例子中,由于一开始我们使用了缺省参数shelve.open()了,因此第6行修改的值即使我们s.close()也不会被保存。

执行结果如下:

$ python shelve_create.py
$ python shelve_withoutwriteback.py

{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'float': 9.5, 'string': 'Sample data'}

所以当我们试图让shelve去自动捕获对象的变化,我们应该在打开shelf的时候将writeback设置为True。当我们将writeback这个flag设置为True以后,shelf将会将所有从DB中读取的对象存放到一个内存缓存。当我们close()打开的shelf的时候,缓存中所有的对象会被重新写入DB。

import shelve

s = shelve.open('test_shelf.db', writeback=True)
try:
  print s['key1']
  s['key1']['new_value'] = 'this was not here before'
  print s['key1']
finally:
  s.close()

s = shelve.open('test_shelf.db', writeback=True)
try:
  print s['key1']
finally:
  s.close()

writeback方式有优点也有缺点。优点是减少了我们出错的概率,并且让对象的持久化对用户更加的透明了;但这种方式并不是所有的情况下都需要,首先,使用writeback以后,shelf在open()的时候会增加额外的内存消耗,并且当DB在close()的时候会将缓存中的每一个对象都写入到DB,这也会带来额外的等待时间。因为shelve没有办法知道缓存中哪些对象修改了,哪些对象没有修改,因此所有的对象都会被写入。

$ python shelve_create.py
$ python shelve_writeback.py
 
{'int': 10, 'float': 9.5, 'string': 'Sample data'}
{'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}
 {'int': 10, 'new_value': 'this was not here before', 'float': 9.5, 'string': 'Sample data'}

最后再来个复杂一点的例子:

#!/bin/env python

import time
import datetime
import md5
import shelve

LOGIN_TIME_OUT = 60
db = shelve.open('user_shelve.db', writeback=True)

def newuser():
  global db
  prompt = "login desired: "
  while True:
    name = raw_input(prompt)
    if name in db:
      prompt = "name taken, try another: "
      continue
    elif len(name) == 0:
      prompt = "name should not be empty, try another: "
      continue
    else:
      break
  pwd = raw_input("password: ")
  db[name] = {"password": md5_digest(pwd), "last_login_time": time.time()}
  #print '-->', db

def olduser():
  global db
  name = raw_input("login: ")
  pwd = raw_input("password: ")
  try:
    password = db.get(name).get('password')
  except AttributeError, e:
    print "\033[1;31;40mUsername '%s' doesn't existed\033[0m" % name
    return
  if md5_digest(pwd) == password:
    login_time = time.time()
    last_login_time = db.get(name).get('last_login_time')
    if login_time - last_login_time < LOGIN_TIME_OUT:
      print "\033[1;31;40mYou already logged in at: <%s>\033[0m" % datetime.datetime.fromtimestamp(last_login_time).isoformat()

    db[name]['last_login_time'] = login_time
    print "\033[1;32;40mwelcome back\033[0m", name
  else:
    print "\033[1;31;40mlogin incorrect\033[0m"

def md5_digest(plain_pass):
  return md5.new(plain_pass).hexdigest()

def showmenu():
  #print '>>>', db
  global db
  prompt = """
(N)ew User Login
(E)xisting User Login
(Q)uit
Enter choice: """
  done = False
  while not done:
    chosen = False
    while not chosen:
      try:
        choice = raw_input(prompt).strip()[0].lower()
      except (EOFError, KeyboardInterrupt):
        choice = "q"
      print "\nYou picked: [%s]" % choice
      if choice not in "neq":
        print "invalid option, try again"
      else:
        chosen = True

    if choice == "q": done = True
    if choice == "n": newuser()
    if choice == "e": olduser()
  db.close()

if __name__ == "__main__":
  showmenu()

感谢阅读本文,希望能帮助到大家,谢谢大家对本站的支持!

Python 相关文章推荐
在Python中使用dict和set方法的教程
Apr 27 Python
Python序列操作之进阶篇
Dec 08 Python
详解 Python 与文件对象共事的实例
Sep 11 Python
基于使用paramiko执行远程linux主机命令(详解)
Oct 16 Python
解决python3读取Python2存储的pickle文件问题
Oct 25 Python
在python plt图表中文字大小调节的方法
Jul 08 Python
python使用正则表达式去除中文文本多余空格,保留英文之间空格方法详解
Feb 11 Python
TensorFlow tf.nn.conv2d_transpose是怎样实现反卷积的
Apr 20 Python
浅谈keras中Dropout在预测过程中是否仍要起作用
Jul 09 Python
Python Opencv图像处理基本操作代码详解
Aug 31 Python
python用700行代码实现http客户端
Jan 14 Python
pytorch实现线性回归以及多元回归
Apr 11 Python
Pyhton中单行和多行注释的使用方法及规范
Oct 11 #Python
使用Python脚本实现批量网站存活检测遇到问题及解决方法
Oct 11 #Python
深入浅析ImageMagick命令执行漏洞
Oct 11 #Python
Zabbix实现微信报警功能
Oct 09 #Python
python 2.6.6升级到python 2.7.x版本的方法
Oct 09 #Python
Django1.7+python 2.78+pycharm配置mysql数据库
Oct 09 #Python
解决python2.7 查询mysql时出现中文乱码
Oct 09 #Python
You might like
php strlen mb_strlen计算中英文混排字符串长度
2009/07/10 PHP
php木马webshell扫描器代码
2012/01/25 PHP
Zend studio文件注释模板设置方法
2013/09/29 PHP
php使用memcoder将视频转成mp4格式的方法
2015/03/12 PHP
PHP利用超级全局变量$_GET来接收表单数据的实例
2016/11/05 PHP
php识别翻转iphone拍摄的颠倒图片
2018/05/17 PHP
php+Ajax处理xml与json格式数据的方法示例
2019/03/04 PHP
非常好的js代码
2006/06/27 Javascript
JavaScript内核之基本概念
2011/10/21 Javascript
各浏览器对document.getElementById等方法的实现差异解析
2013/12/05 Javascript
调用HttpHanlder的几种返回方式小结
2013/12/20 Javascript
JavaScript中自定义事件用法分析
2014/12/23 Javascript
jQuery及JS实现循环中暂停的方法
2015/02/02 Javascript
javascript中数组方法汇总
2015/07/07 Javascript
ES6所改良的javascript“缺陷”问题
2016/08/23 Javascript
如何通过非数字与字符的方式实现PHP WebShell详解
2017/07/02 Javascript
通过示例彻底搞懂js闭包
2017/08/10 Javascript
原生JS实现移动端web轮播图详解(结合Tween算法造轮子)
2017/09/10 Javascript
[05:09]2016国际邀请赛中国区预选赛淘汰赛首日精彩回顾
2016/06/29 DOTA
python应用程序在windows下不出现cmd窗口的办法
2014/05/29 Python
django使用html模板减少代码代码解析
2017/12/12 Python
对python中dict和json的区别详解
2018/12/18 Python
原来我一直安装 Python 库的姿势都不对呀
2019/11/11 Python
pyinstaller打包成无控制台程序时运行出错(与popen冲突的解决方法)
2020/04/15 Python
Django项目创建及管理实现流程详解
2020/10/13 Python
为你的html5网页添加音效示例
2014/04/03 HTML / CSS
HTML5 SEO优化的一些建议
2020/08/27 HTML / CSS
英国手工制作的现代与经典的沙发和床:Love Your Home
2020/09/26 全球购物
网络工程师专家职业发展路线
2014/02/14 职场文书
遗嘱公证书标准样本
2014/04/08 职场文书
大学中国梦演讲稿
2014/04/23 职场文书
禁毒宣传活动总结
2014/08/26 职场文书
会议通知格式范文
2015/04/15 职场文书
情侣之间的道歉短信
2015/05/12 职场文书
党校培训学习心得体会
2016/01/06 职场文书
MYSQL常用函数介绍
2022/05/05 MySQL