8.3. shelve — 实例对象的持久化 | 数据持久和数据交换 |《python 3 标准库实例教程》| python 技术论坛-江南app体育官方入口
目的: shelve 模块实现了对任意可被序列化的 python 对象进行持久性存储,也提供类字典 api 给我们使用。
当使用关系数据库是一种浪费的时候,shelve 模块可以为 python 对象提供一个简单的持久性存储选择。就像使用字典一样,通过关键字访问 shelf 对象。其值经过序列化,写入到由 创建和管理的数据库。
创建一个 shelf 对象
最简单的使用 shelve
模块的方式是通过 dbfilenameshelf
类。 该类使用 来存储数据。你可以直接使用该类,或者调用 shelve.open()
方法。
shelve_create.py
import shelve
with shelve.open('test_shelf.db') as s:
s['key1'] = {
'int': 10,
'float': 9.5,
'string': 'sample data',
}
为了再次访问数据,打开 shelf 并且像字典一样使用它。
shelve_existing.py
import shelve
with shelve.open('test_shelf.db') as s:
existing = s['key1']
print(existing)
如果你运行了上面两个脚本,应该看到:
$ python3 shelve_create.py
$ python3 shelve_existing.py
{'int': 10, 'float': 9.5, 'string': 'sample data'}
模块不支持多个应用同时写入同一数据库。如果你确定客户端不会修改shelf, 请传入 flag='r'
来指定 shelve 以只读方式打开数据库。
shelve_readonly.py
import dbm
import shelve
with shelve.open('test_shelf.db', flag='r') as s:
print('existing:', s['key1'])
try:
s['key1'] = 'new value'
except dbm.error as err:
print('error: {}'.format(err))
当数据库以只读方式打开时,使用者又尝试着更改数据库,这将引起一个访问出错的异常。这一异常类型依赖于在创建数据库时被 选择的数据库模块。
$ python3 shelve_readonly.py
existing: {'int': 10, 'float': 9.5, 'string': 'sample data'}
error: cannot add item to database
writeback模式
默认情况下,shelves 不去追踪可变对象的修改。意思就是,如果你改变了已存储在 shelf 中的一个项目的内容,就必须重新存储该项目来更新 shelf 。
shelve_withoutwriteback.py
import shelve
with shelve.open('test_shelf.db') as s:
print(s['key1'])
s['key1']['new_value'] = 'this was not here before'
with shelve.open('test_shelf.db', writeback=true) as s:
print(s['key1'])
在这个例子中,没有对字典里的关键字 'key1'
的内容进行存储,因此,重新打开 shelf 的时候,并未保存所做的改变。
$ python3 shelve_create.py
$ python3 shelve_withoutwriteback.py
{'int': 10, 'float': 9.5, 'string': 'sample data'}
{'int': 10, 'float': 9.5, 'string': 'sample data'}
为了自动捕捉储存在 shelf 中的可变对象所发生的改变,可以开启 writeback 模式。 writeback
标志使得 shelf 用内存中缓存来记住从数据库中调出的所有对象。当 shelf 关闭的时候,每一个缓存中的对象会重新写入数据库。
shelve_writeback.py
import shelve
import pprint
with shelve.open('test_shelf.db', writeback=true) as s:
print('initial data:')
pprint.pprint(s['key1'])
s['key1']['new_value'] = 'this was not here before'
print('\nmodified:')
pprint.pprint(s['key1'])
with shelve.open('test_shelf.db', writeback=true) as s:
print('\npreserved:')
pprint.pprint(s['key1'])
虽然使用 writeback 模式可以减少程序员出错机率,也能更加透明化对象持久性,但是,不是每种情况都要使用 writeback 模式的。当 shelf 打开的时候,缓存就要占据额外的空间,并且,当 shelf 关闭的时候,也会花费额外的时间去将所有缓存中的对象写入到数据库中。即使不知道缓存中的对象有没有改变,都要写回数据库。如果你的应用程序读取数据多于写入数据,那么 writeback 模式将增大不必要的开销。
$ python3 shelve_create.py
$ python3 shelve_writeback.py
initial data:
{'float': 9.5, 'int': 10, 'string': 'sample data'}
modified:
{'float': 9.5,
'int': 10,
'new_value': 'this was not here before',
'string': 'sample data'}
preserved:
{'float': 9.5,
'int': 10,
'new_value': 'this was not here before',
'string': 'sample data'}
指定 shelf 类型
上面的例子全都使用了默认的 shelf 实现。使用 shelve.open()
直接代替了一种 shelf 实现,是常见用法,尤其是在不关心用哪种数据库存储数据的时候。然而,当我们需要关心这个问题的时候,通常就会直接使用 dbfilenameshelf
或者 bsddbshelf
,甚至通过 shelf
新建子类来自定义一种实现。
扩展阅读
- --
dbm
使用一个可用的 dbm 库来创建一个新的数据库。- --
feedcache
模块使用shelve
做为默认的存储选项。- -- shove 使用更多的后端格式来实现类似的 api 。
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 cc 协议,如果我们的工作有侵犯到您的权益,请及时联系江南app体育官方入口。