You are here:  Home » Python » shelve-Python对象持久性(2)pickle和marshal模块永久存储Python数据(必读进阶Python教程)(参考资料)

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

shelve.openfilenameflag =’c’protocol = Nonewriteback = False 
打开一个持久的字典。指定的文件名是底层数据库的基本文件名。作为副作用,可以向文件名添加扩展名,并且可以创建多个文件。默认情况下,打开底层数据库文件以进行读写。可选的flag参数与flag参数的解释相同dbm.open()

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

由于Python语义,架子无法知道何时修改了可变的持久字典条目。默认情况下,只有在分配给工具架时才会编写修改的对象(请参见示例)。如果可选写回参数设置为True,访问的所有项目也缓存在内存中,并在写回sync()和 close(); 这可以使持久化字典中的可变条目变得更容易,但是,如果访问了许多条目,它可能会占用大量的内存用于缓存,并且它可以使关闭操作非常慢,因为所有访问的条目都被写回(没有办法确定哪些访问的条目是可变的,哪些是实际变异的。

注意

不要靠货架自动关闭; close()当你不再需要它时,总是显式调用 ,或者shelve.open()用作上下文管理器:

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

 

警告

由于shelve模块是备份的pickle,因此从不受信任的源加载架子是不安全的。与pickle一样,加载架子可以执行任意代码。

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

支持另外两种方法:

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

也可以看看

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

限制

  • 选择使用哪个数据库包(例如dbm.ndbm或 dbm.gnu)取决于可用的接口。因此,直接使用打开数据库是不安全的dbm。数据库(不幸的是)也受到限制dbm,如果使用的话 – 这意味着存储在数据库中的对象的(腌制表示)应该相当小,并且在极少数情况下,密钥冲突可能导致数据库拒绝更新。
  • shelve模块不支持对搁置对象的并发读/写访问。(多个同时读取访问是安全的。)当程序打开一个架子进行写入时,没有其他程序可以打开它进行读写。Unix文件锁定可用于解决此问题,但这在Unix版本中有所不同,需要了解所使用的数据库实现。
class shelve.Shelfdictprotocol = Nonewriteback = Falsekeyencoding =’utf-8′ 
其子类collections.abc.MutableMappingdict对象中存储pickle值。

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

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

所述keyencoding参数是用于它们与下面的字典使用之前进行编码密钥的编码。

Shelf目的也可以用作上下文管理器,在这种情况下,它将在自动关闭with块结束。

在3.2版中更改:添加了keyencoding参数; 以前,密钥总是以UTF-8编码。

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

class shelve.BsdDbShelfdictprotocol = Nonewriteback = Falsekeyencoding =’utf-8′ 
子类的Shelf暴露first()next(), previous()last()set_location()是第三方适用于哪些bsddb从模块pybsddb而不是在其他的数据库模块。传递给构造函数的dict对象必须支持这些方法。这通常是通过调用一个完成的 bsddb.hashopen()bsddb.btopen()bsddb.rnopen()。可选协议写回密钥编码参数具有与该类相同的解释Shelf
class shelve.DbfilenameShelffilenameflag =’c’protocol = Nonewriteback = False 
其子类Shelf接受文件名而不是类似dict的对象。将使用打开基础文件dbm.open()。默认情况下,将为读取和写入创建并打开文件。可选标志参数与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