Python学习笔记九10:shelve模块
文章目录
- 7 .shelve模块
- (1) 一个潜在的陷阱
- (2) 一个简单的数据库示例
7 .shelve模块
下一章将介绍如何将数据存储到文件中,但如果需要的是简单的存储方案,模块shelve
可替你完成大部分工作——你只需提供一个文件名即可。
对于模块shelve
,你唯一感兴趣的是函数open
。这个函数将一个文件名作为参数,并返回一个Shelf对象
,供你用来存储数据。你可像操作普通字典那样操作它(只是键必须为字符串),操作完毕(并将所做的修改存盘)时,可调用其方法close
。
(1) 一个潜在的陷阱
至关重要的一点是认识到shelve.open
返回的对象并非普通映射,如下例所示:
>>> import shelve
>>> s = shelve.open('test.dat')
>>> s['x'] = ['a', 'b', 'c']
>>> s['x'].append('d')
>>> s['x'] #['a', 'b', 'c']
这很容易解释:当你查看shelf对象
中的元素时,将使用存储版重建该对象,而当你将一个元素赋给键时,该元素将被存储。在上述示例中,发生的事情如下。
- 列表[‘a’, ‘b’, ‘c’]被存储到s的’x’键下。
- 获取存储的表示,并使用它创建一个新列表,再将’d’附加到这个新列表末尾,但这个修改后的版本未被存储!
- 最后,再次获取原来的版本——其中没有’d’。
要正确地修改使用模块shelve
存储的对象,必须将获取的副本赋给一个临时变量,并在修改这个副本后再次存储:
>>> temp = s['x']
>>> temp.append('d')
>>> s['x'] = temp
>>> s['x'] #['a', 'b', 'c', 'd']
还有另一种避免这个问题的办法:将函数open
的参数writeback
设置为True
。这样,从shelf对象
读取或赋给它的所有数据结构都将保存到内存(缓存)中,并等到你关闭shelf对象
时才将它们写入磁盘中。如果你处理的数据不多,且不想操心这些问题,将参数writeback
设置为True
可能是个不错的主意。在这种情况下,你必须确保在处理完毕后将shelf对象
关闭。为此,一种办法是像处理打开的文件那样,将shelf对象用作上下文管理器,这将在下一章讨论。
(2) 一个简单的数据库示例
代码清单10-8是一个使用模块shelve
的简单数据库应用程序。
# database.py
import sys, shelve
def store_person(db): """让用户输入数据并将其存储到shelf对象中"""pid = input('Enter unique ID number: ')person = {}person['name'] = input('Enter name: ')person['age'] = input('Enter age: ')person['phone'] = input('Enter phone number: ')db[pid] = persondef lookup_person(db):"""让用户输入ID和所需的字段,并从shelf对象中获取相应的数据"""pid = input('Enter ID number: ')field = 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 commands are:')print('store : Stores information about a person')print('lookup : Looks up a person from ID number')print('quit : Save changes and exit')print('? : Prints this message')def enter_command():'''输入想要实现的功能'''cmd = input('Enter command (? for help): ')cmd = cmd.strip().lower()return cmddef main():database = shelve.open('C:\\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':returnfinally:database.close()
if name == '__main__': main()
代码清单10-8所示的程序有几个有趣的特征。
- 所有代码都放在函数中,这提高了程序的结构化程度(一个可能的改进是将这些函数作为一个类的方法)。
- 主程序位于函数main中,这个函数仅在
__name__== '__main__'
时才会被调用。这意味着可在另一个程序中将这个程序作为模块导入,再调用函数main
。 - 在
函数main
中,我打开一个数据库(shelf),再将其作为参数传递给其他需要它的函数。由于这个程序很小,我原本可以使用一个全局变量,但在大多数情况下,最好不要使用全局变量——除非你有理由这样做。 - 读入一些值后,我调用
strip
和lower
来修改它们,因为仅当提供的键与存储的键完全相同时,它们才匹配。如果对用户输入的内容都调用strip
和lower
,用户输入时就无需太关心大小写,且在输入开头和末尾有多余的空白也没有关系。另外,注意到打印字段名时使用了capitalize
。 - 为确保数据库得以妥善的关闭,我使用了try和finally。不知道什么时候就会出现问题,进而引发异常。如果程序终止时未妥善地关闭数据库,数据库文件可能受损,变得毫无用处。通过使用
try和finally
,可避免这样的情况发生。我原本也可像第11章介绍的那样,将shelf
用作上下文管理器。
我们来试试这个数据库。下面是一个示例交互过程:
Enter command (? for help): ?
The available commands are:
store : Stores information about a person
lookup : Looks up a person from ID number
quit : Save changes and exit
? : Prints this message
Enter command (? for help): store
Enter unique ID number: 001
Enter name: Mr. Gumby
Enter age: 42
Enter phone number: 555-1234
Enter command (? for help): lookup
Enter ID number: 001
What would you like to know? (name, age, phone) phone
Phone: 555-1234
Enter command (? for help): quit
这个交互过程并不是很有趣。我原本可以使用普通字典(而不是shelf对象
)来完成这个任务。退出这个程序后,来看看再次运行它时(这也许是在第二天)发生的情况。
Enter command (? for help): lookup
Enter ID number: 001
What would you like to know? (name, age, phone) name
Name: Mr. Gumby
Enter command (? for help): quit
如你所见,这个程序读取前面运行它时创建的文件,该文件依然包含Mr. Gumby!
提示:如果要以这样的格式保存数据,也就是让使用其他语言编写的程序能够轻松地读取它们,可考虑使用JSON格式
。Python标准库提供了用于处理JSON字符串(在这种字符串和Python值之间进行转换)的模块json。
Python学习笔记九10:shelve模块相关推荐
- Python学习笔记:常用第三方模块(1)
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记:常用第三方模块3
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记:常用内建模块7XML
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记:常用内建模块5
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记:常用内建模块2:collections
前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...
- Python学习笔记(迭代、模块扩展、GUI 、编码处理等)
PythonIDLE中的编码处理 http://www.tuicool.com/articles/NbyEBr 原文标题:Python中实际上已经得到了正确的Unicode或某种编码的字符,但是看起来 ...
- Python学习笔记九:文件I/O
打印到屏幕: 1 #!/usr/bin/python 2 3 print "Python is really a great language,", "isn't it? ...
- 【懒懒的Python学习笔记九】
至此,已经掌握了Python的基本技能,在本章中将学习如何进行文件操作. 文件操作 从文件中读取文件 文本数据可存储大量数据,每当需要分析或者修改存储在文件中的信息的时候,读取文件就显得至关重要了. ...
- python学习笔记(10)--组合数据类型(序列类型)
序列是具有先后关系的一组数据,是一维元素向量,元素类型可以不同,类似数学元素序列,元素间由序号引导,通过下标访问序列的特定元素.序列类型是一个基类类型,字符串类型,元祖类型,列表类型都属于序列类型. ...
最新文章
- seaborn系列(1) | 关系类图relplot用法
- JAVA入门级教学之(编写第一个HelloWorld程序)
- 跨平台的PHP+MySQL_跨平台的PHP+MySQL
- 精品、好用、优质、黑科技网站推荐
- java jsp网页模板_JSP网页模板
- 循环冗余校验码(计算机组成原理12)
- python vcf转换xls的简单实现
- 盘点“大宗商品电子交易模式”的8种交易流程
- 【无标题】2021年烷基化工艺证考试及烷基化工艺操作证考试
- 搭建阿里云Linux版服务器+使用docker安装EMQ、Node-RED、MySQL+本地Navicat访问数据库(增删改查)——详细流程
- unity的C#学习——标识符号、关键字与数据类型及其转换方式
- 动画效果html5,HTML5动画效果
- 反向题在测试问卷信效度_如何确认问卷(考卷)的信度与效度?
- 【VBA研究】如何将单元格数据赋给数组
- VisionMobile:2011年智能手机数据
- 入门算法:小和问题 之归并排序思想 java语言
- 刘宇凡:什么是内链?什么是外链?
- 微软CEO发话:今年停止加薪并减少奖金,网友:总比失业好!
- 李松军当选俄罗斯自然科学院和乌克兰国家工程院外籍院士
- es文件浏览器怎么开ftp服务器,es文件浏览器怎么建立ftp服务器
热门文章
- oppoa57计算机有存储功能吗,虽是入门级产品,但OPPO A57这两个功能值得称赞
- Linux时间戳timestamp导致端口不通
- debian下基本系统和gnome桌面安装
- 华为OD机试Golang解题 - 获得完美走位
- 一行能装逼的JavaScript代码
- Android点击空白处隐藏软键盘
- hash为什么这么快?
- java矩阵addall_为什么Collections.addAll()比arrays.addAll()性能好?
- IMF(Internet Message Format)简介
- 06-[案例1]鼠标移出移入控制二维码的显示与隐藏