11.4. 搁置 — Python 对象持久性 — Python 文档

来自菜鸟教程
Python/docs/2.7/library/shelve
跳转至:导航、​搜索

11.4. 搁置 — Python 对象持久化

源代码: :source:`Lib/shelve.py`



“架子”是一个持久的、类似字典的对象。 与“dbm”数据库的不同之处在于,shelf 中的值(不是键!)本质上可以是任意的 Python 对象——pickle 模块可以处理的任何对象。 这包括大多数类实例、递归数据类型和包含大量共享子对象的对象。 键是普通字符串。

shelve.open(filename, flag='c', protocol=None, writeback=False)

打开持久字典。 指定的文件名是基础数据库的基本文件名。 作为一种副作用,可能会向文件名添加扩展名,并且可能会创建多个文件。 默认情况下,底层数据库文件打开进行读写。 可选的 flag 参数与 anydbm.open()flag 参数具有相同的解释。

默认情况下,版本 0 的泡菜用于序列化值。 pickle 协议的版本可以通过 protocol 参数指定。

2.3 版更改: 添加了 协议 参数。

由于 Python 语义,架子无法知道何时修改了可变持久字典条目。 默认情况下,修改后的对象在分配到架子时仅写入 ' (参见 示例 )。 如果可选的 writeback 参数设置为 True,所有访问的条目也会缓存在内存中,并写回 sync()close() ; 这可以更方便地改变持久字典中的可变条目,但是,如果访问了许多条目,它可能会消耗大量内存用于缓存,并且由于所有访问的条目都被写回,因此可能会使关闭操作变得非常缓慢(无法确定哪些访问的条目是可变的,也无法确定哪些条目实际上发生了变异)。

与文件对象一样,搁置对象应明确关闭以确保将持久数据刷新到磁盘。

警告

因为 shelf 模块由 pickle 支持,所以从不受信任的来源加载一个架子是不安全的。 与 pickle 一样,加载一个架子可以执行任意代码。


Shelf 对象支持字典支持的大多数方法。 这简化了从基于字典的脚本到需要持久存储的脚本的过渡。

请注意,不支持 Python 3 转换方法(viewkeys()viewvalues()viewitems())。

支持另外两种方法:

Shelf.sync()
如果架子是在 writeback 设置为 True 的情况下打开的,则写回缓存中的所有条目。 如果可行,还清空缓存并同步磁盘上的持久字典。 当使用 close() 关闭架子时,会自动调用此方法。
Shelf.close()
同步并关闭持久化的 dict 对象。 在封闭架子上的操作将失败并显示 ValueError

也可以看看

持久字典配方具有广泛支持的存储格式并具有本地字典的速度。


11.4.1. 限制


  • 选择使用哪个数据库包(例如 dbmgdbmbsddb)取决于哪个接口可用。 因此直接使用dbm打开数据库是不安全的。 数据库也(不幸地)受到 dbm 的限制,如果使用它——这意味着存储在数据库中的对象(腌制表示)应该相当小,并且在极少数情况下是关键冲突可能导致数据库拒绝更新。
  • shelve 模块不支持 concurrent 对搁置对象的读/写访问。 (多个同时读访问是安全的。)当一个程序有一个为写而打开的架子时,没有其他程序应该打开它以进行读或写。 Unix 文件锁定可用于解决此问题,但这因 Unix 版本而异,并且需要了解所使用的数据库实现。
class shelve.Shelf(dict, protocol=None, writeback=False)

UserDict.DictMixin 的子类,它在 dict 对象中存储腌制值。

默认情况下,版本 0 的泡菜用于序列化值。 pickle 协议的版本可以通过 protocol 参数指定。 有关 pickle 协议的讨论,请参阅 pickle 文档。

2.3 版更改: 添加了 协议 参数。

如果 writeback 参数为 True,则对象将保存所有访问条目的缓存,并在同步和关闭时间将它们写回 dict。 这允许对可变条目进行自然操作,但会消耗更多内存并使同步和关闭需要很长时间。

class shelve.BsdDbShelf(dict, protocol=None, writeback=False)
Shelf 的子类,它公开了 first()next()previous()last()set_location() bsddb 模块,但不在其他数据库模块中。 传递给构造函数的 dict 对象必须支持这些方法。 这通常通过调用 bsddb.hashopen()bsddb.btopen()bsddb.rnopen() 之一来完成。 可选的 protocolwriteback 参数与 Shelf 类具有相同的解释。
class shelve.DbfilenameShelf(filename, flag='c', protocol=None, writeback=False)
Shelf 的子类,它接受 文件名 而不是类似 dict 的对象。 底层文件将使用 anydbm.open() 打开。 默认情况下,文件将被创建和打开以进行读取和写入。 可选的 flag 参数与 open() 函数具有相同的解释。 可选的 protocolwriteback 参数与 Shelf 类具有相同的解释。


11.4.2. 例子

总结一下接口(key 是一个字符串,data 是一个任意对象):

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 = d.has_key(key)   # true if the key exists
klist = d.keys() # a list of all existing keys (slow!)

# as d was opened WITHOUT writeback=True, beware:
d['xx'] = range(4)  # this works as expected, but...
d['xx'].append(5)   # *this doesn't!* -- d['xx'] is STILL range(4)!

# 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

也可以看看

模块 anydbm
dbm 样式数据库的通用接口。
模块 bsddb
BSD db 数据库接口。
模块 dbhash
bsddb 周围的薄层,它提供了一个 open() 函数,就像其他数据库模块一样。
模块 dbm
标准的 Unix 数据库接口。
模块 dumbdbm
dbm 接口的便携式实现。
模块 gdbm
GNU 数据库接口,基于 dbm 接口。
模块 pickle
shelve 使用的对象序列化。
模块 cPickle
pickle的高性能版本。