Tkinter与shelve结合构建database
本帖最后由 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 = data # store data at key (overwrites old data if
# using an existing key)
data = d # retrieve a COPY of data at key (raise KeyError
# if no such key)
del d # 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'] = # this works as expected, but...
d['xx'].append(3) # *this doesn't!* -- d['xx'] is STILL !
# 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的年龄之后更新的数据库数据
上图是增加新的键值及数据之后数据库中保存的数据
代码如下:
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 = 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获取数据,并在GUI中显示
except: #发生异常时执行的代码
showerror(title='Error', message='No such key!')#异常处理,弹出error窗口,显示No such key!
else:#没有异常时执行的代码
for field in fieldnames:
entries.delete(0, END)
entries.insert(0, repr(getattr(record, field)))
#应用函数updaterecord
def updateRecord():
key = entries['key'].get()
if key in db:
record = db #更新已有记录
else:
#在该键下生成/保存新记录
record = Person(name='?', age='?') #字符串用引号引起来
for field in fieldnames:
setattr(record, field, eval(entries.get()))
db = record
window = makeWidgets()
window.mainloop()
db.close()
页:
[1]