|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 Handsome_zhou 于 2020-10-20 11:10 编辑
"Shelf" 是一种持久化的类似字典的对象。 与 "dbm" 数据库的区别在于 Shelf 中的值(不是键!)实际上可以为任意 Python 对象 --- 即 pickle 模块能够处理的任何东西。 这包括大部分类实例、递归数据类型,以及包含大量共享子对象的对象。 键则为普通的字符串。
shelve.open(filename, flag='c', protocol=None, writeback=False)
打开一个持久化字典。filename指定下层数据库的基准文件名。默认情况下,下层数据库会以读写模式打开。默认会使用第三版pickle协议来序列化值。pickle协议版本可通过protocol形参来指定。
由于Python的语义的限制,Shelve对象无法确定一个可变的持久化字典条目在何时被修改。默认情况下,只有在被修改对象再复制给shelve时才会写入该对象。
示例:
- import shelve
- d = shelve.open(filename) # open -- file may get suffix added by low-level
- # library
- d[key] = data # store data at key (overwrites old data if
- # using an existing key)
- data = d[key] # retrieve a COPY of data at key (raise KeyError
- # if no such key)
- del d[key] # delete data stored at key (raises KeyError
- # if no such key)
- flag = key in d # true if the key exists
- klist = list(d.keys()) # a list of all existing keys (slow!)
- # as d was opened WITHOUT writeback=True, beware:
- d['xx'] = [0, 1, 2] # this works as expected, but...
- d['xx'].append(3) # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!
- # having opened d without writeback=True, you need to code carefully:
- temp = d['xx'] # extracts the copy
- temp.append(5) # mutates the copy
- d['xx'] = temp # stores the copy right back, to persist it
- # or, d=shelve.open(filename,writeback=True) would let you just code
- # d['xx'].append(5) and have it work as expected, BUT it would also
- # consume more memory and make the d.close() operation slower.
- d.close() # close it
复制代码
使用shelve时不要依赖shelve的自动关闭功能,使用结束时应该显式的调用close()。
因为shelve可以进行数据的持久化,而tkinter的功能也是非常的丰富,可以很方便的做出一个界面来。那么与tkinter结合起来就可以构建一个可以自由提取和更新数据的数据库了。
上图是数据库界面
上图是输入键值sue之后提取的原始数据库数据
上图是对sue的年龄修改后数据库中更新后的数据
上图是更改sue的年龄之后更新的数据库数据
上图是增加新的键值及数据之后数据库中保存的数据
代码如下:
- from tkinter import *
- from tkinter.messagebox import showerror
- import shelve
- fieldnames = ('name','age','job','pay')
- class Person:
- def __init__(self,name,age,pay=0,job=None):
- self.name = name
- self.age = age
- self.pay = pay
- self.job = job
- if __name__ == '__main__':
- bob = Person('Bob Smith',42,30000,'software')
- sue = Person('Sue Jones',45,40000,'hardware')
- db = shelve.open('class-shelve')
- db['bob'] = bob
- db['sue'] = sue
- #定义函数
- def makeWidgets():
- global entries #声明entries为全局变量
- window = Tk() #创建根窗口
- window.title('People Shelve')
- form = Frame(window) #控键在屏幕上显示一个矩形区域,多用来作为容器 ,这里的根窗口相当与变为form
- form.pack() #框架打包
- entries = {} #创建entries字典
- for (ix, label) in enumerate(('key',) + fieldnames): #for 索引,值 在元组中,元组中的值比原fildnames增加一个'key'
- lab = Label(form, text=label) #把标签显示在矩形区域内,赋给变量lab
- ent = Entry(form) #把矩形区域输入的值赋给变量ent
- lab.grid(row=ix, column=0) #把标签放在第一列
- ent.grid(row=ix, column=1,padx=10,pady=5) #把输入值放在第二列
- entries[label] = ent #为字典对应的键赋值
- Button(window, text="Fetch", command=fetchRecord).pack(side=LEFT)
- Button(window, text="Update", command=updateRecord).pack(side=LEFT)
- Button(window, text="Quit", command=window.quit).pack(side=RIGHT)
- return window
- #应用函数fetchrecord
- def fetchRecord():
- key = entries['key'].get()
- try: #执行代码
- record = db[key] #使用key获取数据,并在GUI中显示
- except: #发生异常时执行的代码
- showerror(title='Error', message='No such key!') #异常处理,弹出error窗口,显示No such key!
- else: #没有异常时执行的代码
- for field in fieldnames:
- entries[field].delete(0, END)
- entries[field].insert(0, repr(getattr(record, field)))
- #应用函数updaterecord
- def updateRecord():
- key = entries['key'].get()
- if key in db:
- record = db[key] #更新已有记录
- else:
- #在该键下生成/保存新记录
- record = Person(name='?', age='?') #字符串用引号引起来
- for field in fieldnames:
- setattr(record, field, eval(entries[field].get()))
- db[key] = record
- window = makeWidgets()
- window.mainloop()
- db.close()
复制代码 |
|