Shelve---Python对象持久性:
“shelf”是一个持久的,类似字典的对象。与“dbm”数据库的区别在于,shelf中的values(而不是keys!)可以是基本上任意的Python对象 - pickle模块可以处理的任何东西。这包括大多数类实例,递归数据类型和包含许多共享子对象的对象。key是普通的字符串。
shelve.open(filename,flag ='c',protocol = None,writeback = False)
打开一个持久的字典。指定的文件名是底层数据库的基本文件名。作为副作用,可以向文件名添加扩展名,并且可以创建多个文件。默认情况下,打开底层数据库文件以进行读写。可选的flag参数与anydbm.open()的flag参数具有相同的解释。
由于Python语义,"shelf"无法知道何时修改了可变的持久字典条目。默认情况下,只有在分配给工具架时才会编写修改的对象(请参见示例)。如果可选的writeback参数设置为True,则访问的所有条目也会缓存在内存中,并写回sync()和close();这可以使持久化字典中的可变条目变得更容易,但是,如果访问了许多条目,它可能会占用大量的内存用于缓存,并且它可以使关闭操作非常慢,因为所有访问的条目都被写回(没有办法确定哪些访问的条目是可变的,哪些是实际变异的。)
与文件对象一样,应该显式关闭搁置对象以确保将持久数据刷新到磁盘。
限制:
选择使用哪个数据库包(例如dbm,gdbm或bsddb)取决于可用的接口。因此,使用dbm直接打开数据库是不安全的。数据库(不幸的是)也受到dbm的限制,如果使用的话 - 这意味着存储在数据库中的对象的(腌制表示)应该相当小,并且在极少数情况下,密钥冲突可能导致数据库拒绝更新。
搁置模块不支持对搁置对象的并发读/写访问。 (多个同时读取访问是安全的。)当程序打开一个架子进行写入时,没有其他程序可以打开它进行读写。 Unix文件锁定可用于解决此问题,但这在Unix版本中有所不同,需要了解所使用的数据库实现。
class shelve.Shelf(dict,protocol = None,writeback = False)
UserDict.DictMixin的子类,用于在dict对象中存储pickled值。
如果writeback参数为True,则对象将保存所有访问条目的缓存,并在同步和关闭时将它们写回dict。这允许对可变条目进行自然操作,但是可以消耗更多内存并使同步和关闭需要很长时间。
class shelve.BsdDbShelf(dict,protocol = None,writeback = False)
Shelf的子类,它暴露了bsddb模块中可用但不在其他数据库模块中的first(),next(),previous(),last()和set_location()。传递给构造函数的dict对象必须支持这些方法。这通常通过调用bsddb.hashopen(),bsddb.btopen()或bsddb.rnopen()之一来完成。可选协议和写回参数与Shelf类具有相同的解释。
class shelve.DbfilenameShelf(filename,flag ='c',protocol = None,writeback = False)
Shelf的子类,它接受文件名而不是类似dict的对象。将使用anydbm.open()打开基础文件。默认情况下,将为读取和写入创建并打开文件。可选的flag参数与open()函数的解释相同。可选协议和写回参数与Shelf类具有相同的解释。
例子:
总结接口(键(key)是字符串,数据(data)是任意对象):
import shelve
d = shelve.open(filename) # 打开一个文件,可能会被低级库添加后缀
d[key] = data # 存储一个数据(如果使用现有的key,则覆盖旧数据)
data = d[key] # 取回COPY的数据给key (如果没有这个key,则会返回一个KeyError)
del d[key] #删除key中存储的数据 (如果没有这个key,则会返回一个KeyError)
flag = d.has_key(key) # 如果key存在,则返回True
klist = d.keys() # 所有现有的Key的列表 (慢!)
# as d was opened WITHOUT writeback=True, beware:
d['xx'] = range(4) # 按预期工作
d['xx'].append(5) # *操作不合法!* -- d['xx'] 的范围依然是4
# having opened d without writeback=True, you need to code carefully:
temp = d['xx'] # 提取副本
temp.append(5) # 改变副本(添加第五项)
d['xx'] = temp # 存储副本
# 或者,d = shelve.open(filename,writeback = True)可以让你只编码
#d ['xx'].append(5)并让它按预期工作,但它也会消耗更多的内存并使d.close ()操作较慢。
d.close() # 关闭