shelve ——python对象持久性

源代码: Lib/shelve.py


“工具架”是一个持久的、类似字典的物体。与“dbm”数据库的区别在于值(而不是键!)在一个工具架中,基本上可以是任意的python对象——任何 pickle 模块可以处理。这包括大多数类实例、递归数据类型和包含大量共享子对象的对象。钥匙是普通的弦。

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

打开持久字典。指定的文件名是基础数据库的基本文件名。作为副作用,扩展名可以添加到文件名中,并且可以创建多个文件。默认情况下,打开基础数据库文件进行读写。可选的 flag 参数的解释与 flag 参数 dbm.open() .

默认情况下,使用创建的泡菜 pickle.DEFAULT_PROTOCOL 用于序列化值。PICKLE协议的版本可以使用 协议 参数。

由于python语义的原因,工具架无法知道何时修改可变的持久字典条目。默认情况下,将写入修改的对象 only 分配到货架时(请参见 例子 )如果可选 写回 参数设置为 True ,所有访问的条目也缓存在内存中,并写回 sync()close() ;这可以更容易地改变持久字典中的可变条目,但是,如果访问了许多条目,它会为缓存消耗大量的内存,并且由于所有访问的条目都被写回(无法确定哪些访问的条目是可变的,哪些是可变的,哪些是可变的),所以关闭操作会非常慢。真的变异了)。

在 3.10 版更改: pickle.DEFAULT_PROTOCOL 现在用作默认的PICLE协议。

注解

不要依赖自动关闭的架子;总是调用 close() 当你不再需要它的时候,或者使用它 shelve.open() 作为上下文管理器:

with shelve.open('spam') as db:
    db['eggs'] = 'eggs'

警告

因为 shelve 模块由支持 pickle ,从不受信任的源加载货架是不安全的。和pickle一样,加载一个工具架可以执行任意代码。

工具架对象支持字典支持的所有方法。这简化了从基于字典的脚本到需要持久存储的脚本的转换。

支持两种附加方法:

Shelf.sync()

如果工具架是用 写回 设置为 True . 如果可行,也清空缓存并同步磁盘上的持久字典。当架子用 close() .

Shelf.close()

同步并关闭持久 dict 对象。在封闭的架子上操作会失败 ValueError .

参见

Persistent dictionary recipe 具有广泛支持的存储格式和本机字典的速度。

限制

  • 选择要使用的数据库包(例如 dbm.ndbmdbm.gnu )取决于哪个接口可用。因此,直接使用 dbm . 数据库(不幸的是)也受到 dbm ,如果使用它---这意味着(pickled表示)存储在数据库中的对象应该相当小,在极少数情况下,键冲突可能会导致数据库拒绝更新。

  • 这个 shelve 模块不支持 同时发生的 对搁置对象的读/写访问。(多个同时读取访问是安全的。)当一个程序有一个可供写入的架子时,任何其他程序都不应将其打开以供读取或写入。可以使用Unix文件锁定来解决这一问题,但这在不同的Unix版本中有所不同,需要了解所使用的数据库实现。

class shelve.Shelf(dict, protocol=None, writeback=False, keyencoding='utf-8')

一个子类 collections.abc.MutableMapping 哪些存储泡菜值 dict 对象。

默认情况下,使用创建的泡菜 pickle.DEFAULT_PROTOCOL 用于序列化值。PICKLE协议的版本可以使用 协议 参数。请参阅 pickle 有关泡菜协议的讨论的文档。

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

这个 键控编码 参数是用于在密钥与基础dict一起使用之前对其进行编码的编码。

A Shelf 对象也可以用作上下文管理器,在这种情况下,当 with 块结束。

在 3.2 版更改: 增加了 键控编码 参数;以前,密钥总是以UTF-8编码的。

在 3.4 版更改: 添加了上下文管理器支持。

在 3.10 版更改: pickle.DEFAULT_PROTOCOL 现在用作默认的PICLE协议。

class shelve.BsdDbShelf(dict, protocol=None, writeback=False, keyencoding='utf-8')

一个子类 Shelf 暴露的 first()next()previous()last()set_location() 第三方提供的 bsddb 模块从 pybsddb 但不在其他数据库模块中。这个 dict 传递给构造函数的对象必须支持这些方法。这通常是通过调用 bsddb.hashopen()bsddb.btopen()bsddb.rnopen() . 可选的 协议写回键控编码 参数的解释与 Shelf 类。

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

一个子类 Shelf 接受一个 filename 而不是听写式的物体。将使用打开基础文件 dbm.open() . 默认情况下,将为读和写创建和打开文件。可选的 flag 参数的解释与 open() 功能。可选的 协议写回 参数的解释与 Shelf 类。

例子

总结界面 (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 = 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'] = [0, 1, 2]        # this works as expected, but...
d['xx'].append(3)          # *this doesn't!* -- d['xx'] is STILL [0, 1, 2]!

# 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

参见

模块 dbm

通用接口到 dbm -样式数据库。

模块 pickle

对象序列化由使用 shelve .