shelve-Python 对象持久性

源代码: Lib/shelve.py


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

  • shelve. open(* filename flag ='c' protocol = None writeback = False *)
    • 打开一个持久字典。指定的文件名是基础数据库的基本文件名。作为副作用,可以将 extensions 添加到文件名中,并且可以创建多个文件。默认情况下,基础数据库文件被打开以进行读取和写入。可选的* flag 参数与dbm.open() flag *参数具有相同的解释。

默认情况下,版本 3 的 pickle 用于序列化值。可以使用* protocol *参数指定 pickle 协议的版本。

由于 Python 的语义,货架无法得知何时修改了可变持久词典条目。默认情况下,将修改后的对象分配给书架时仅写入(请参见Example)。如果可选的* writeback *参数设置为True,则所有访问的条目也将缓存在内存中,并写回到sync()close()上;这样可以更容易地更改持久性词典中的可变条目,但是,如果访问了许多条目,则可能会占用大量内存用于缓存,并且由于所有访问的条目都被写回,因此它会使关闭操作非常慢(无法确定哪些访问的条目是可变的,也没有确定哪些实际上是突变的)。

Note

不要依靠架子自动关闭;不再需要时,请始终显式调用close(),或使用shelve.open()作为上下文 Management 器:

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

Warning

由于shelve模块由pickle支持,因此从不受信任的来源加载书架是不安全的。像 pickle 一样,装载架子可以执行任意代码。

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

支持两种其他方法:

  • Shelf. sync ( )

    • 如果在* writeback *设置为True的情况下打开了架子,请写回缓存中的所有条目。如果可行,还清空缓存并同步磁盘上的持久字典。当用close()关闭书架时,将自动调用此方法。
  • Shelf. close ( )

    • 同步并关闭持久* dict *对象。封闭式货架上的操作将失败,并带有ValueError

See also

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

Restrictions

Note

  • 使用哪种数据库包(例如dbm.ndbmdbm.gnu)的选择取决于可用的接口。因此,直接使用dbm打开数据库是不安全的。如果使用了数据库,则数据库也会(不幸地)受到dbm的限制-这意味着存储在数据库中的对象(的腌制形式)应该很小,并且在极少数情况下,键冲突可能会导致数据库崩溃。拒绝更新。

  • shelve模块不支持对并置对象的* concurrent *读/写访问。 (安全的同时进行多个读取访问是安全的.)当一个程序有一个可供写的架子时,其他任何程序都不应将其打开以供读或写。可以使用 Unix 文件锁定来解决此问题,但这在 Unix 版本之间有所不同,并且需要有关所用数据库实现的知识。

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

默认情况下,版本 3 的 pickle 用于序列化值。可以使用* protocol *参数指定 pickle 协议的版本。请参阅pickle文档,以获取有关腌制协议的讨论。

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

  • keyencoding *参数是用于在与基础 dict 一起使用键之前对键进行编码的编码。

Shelf对象也可用作上下文 Management 器,在这种情况下,当with块结束时,它将自动关闭。

在 3.2 版中进行了更改:添加了* keyencoding *参数;以前,密钥始终以 UTF-8 编码。

在版本 3.4 中进行了更改:添加了上下文 Management 器支持。

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

Example

总结接口(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

See also

  • Module dbm

  • dbm样式数据库的通用接口。

  • Module pickle

  • shelve使用的对象序列化。