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 。

本文章首发在 江南app体育官方入口 网站上。

本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 cc 协议,如果我们的工作有侵犯到您的权益,请及时联系江南app体育官方入口。

原文地址:https://learnku.com/docs/pymotw/shelve-p...

译文地址:https://learnku.com/docs/pymotw/shelve-p...

上一篇 下一篇
讨论数量: 0



暂无话题~
网站地图