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编程实现数学运算求一元二次方程的实根算法示例
Apr 02 Python
python 中random模块的常用方法总结
Jul 08 Python
老生常谈Python之装饰器、迭代器和生成器
Jul 26 Python
通过Python 获取Android设备信息的轻量级框架
Dec 18 Python
python之消除前缀重命名的方法
Oct 21 Python
Python Django给admin添加Action的方法实例详解
Apr 29 Python
Python实现操纵控制windows注册表的方法分析
May 24 Python
python+openCV利用摄像头实现人员活动检测
Jun 22 Python
pyecharts在数据可视化中的应用详解
Jun 08 Python
你需要学会的8个Python列表技巧
Jun 24 Python
Python如何导出导入所有依赖包详解
Jun 08 Python
使用Python通过企业微信应用给企业成员发消息
Apr 18 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 遍历数据表数据并列表横向排列的代码
2009/09/05 PHP
在IIS下安装PHP扩展的方法(超简单)
2017/04/10 PHP
PHP API接口必备之输出json格式数据示例代码
2017/06/27 PHP
PHP基于双向链表与排序操作实现的会员排名功能示例
2017/12/26 PHP
javascript KeyDown、KeyPress和KeyUp事件的区别与联系
2009/12/03 Javascript
window.js 主要包含了页面的一些操作
2009/12/23 Javascript
JavaScript中switch判断容易犯错的一个细节
2014/08/27 Javascript
JavaScript中的数组特性介绍
2014/12/30 Javascript
javascript中in运算符用法分析
2015/04/28 Javascript
jQuery插件HighCharts实现的2D回归直线散点效果示例【附demo源码下载】
2017/03/09 Javascript
Vue中正确使用jQuery的方法
2017/10/30 jQuery
原生JavaScript实现todolist功能
2018/03/02 Javascript
JS实现的简单tab切换功能完整示例
2019/06/20 Javascript
vue登录注册实例详解
2019/09/14 Javascript
Node中对非阻塞I/O、事件循环的知识点总结
2020/01/05 Javascript
Python编写一个闹钟功能
2017/07/11 Python
python3 破解 geetest(极验)的滑块验证码功能
2018/02/24 Python
python输入错误后删除的方法
2019/10/12 Python
python ftplib模块使用代码实例
2019/12/31 Python
python与c语言的语法有哪些不一样的
2020/09/13 Python
利用Python将多张图片合成视频的实现
2020/11/23 Python
使用python tkinter开发一个爬取B站直播弹幕工具的实现代码
2021/02/07 Python
Reebok俄罗斯官方网上商店:购买锐步运动服装和鞋子
2016/09/26 全球购物
ABOUT YOU罗马尼亚:超过600个时尚品牌
2019/09/19 全球购物
武汉世纪畅想数字传播有限公司 .NET笔试题
2015/06/13 面试题
乐观大学生的自我评价
2014/01/10 职场文书
个人自我剖析材料
2014/02/07 职场文书
酒店开业庆典主持词
2014/03/21 职场文书
基层党建工作宣传标语
2014/06/24 职场文书
法人代表身份证明书及授权委托书
2014/09/16 职场文书
出差报告范文
2014/11/06 职场文书
中学生打架检讨书之500字
2019/08/06 职场文书
详解python网络进程
2021/06/15 Python
javascript之Object.assign()的痛点分析
2022/03/03 Javascript
Elasticsearch 基本查询和组合查询
2022/04/19 Python
Windows server 2003卸载和安装IIS的图文教程
2022/07/15 Servers