"""Manage shelves of pickled objects.A "shelf" is a persistent, dictionary-like object. The differencewith dbm databases is that the values (not the keys!) in a shelf canbe essentially arbitrary Python objects -- anything that the "pickle"module can handle. This includes most class instances, recursive datatypes, and objects containing lots of shared sub-objects. The keysare ordinary strings.To summarize the interface (key is a string, data is an arbitraryobject):import shelved = shelve.open(filename) # open, with (g)dbm filename -- no suffixd[key] = data # store data at key (overwrites old data if# using an existing key)data = d[key] # retrieve a COPY of the data at key (raise# KeyError if no such key) -- NOTE that this# access returns a *copy* of the entry!del d[key] # delete data stored at key (raises KeyError# if no such key)flag = key in d # true if the key existslist = d.keys() # a list of all existing keys (slow!)d.close() # close itDependent on the implementation, closing a persistent dictionary mayor may not be necessary to flush changes to disk.Normally, d[key] returns a COPY of the entry. This needs care whenmutable entries are mutated: for example, if d[key] is a list,d[key].append(anitem)does NOT modify the entry d[key] itself, as stored in the persistentmapping -- it only modifies the copy, which is then immediatelydiscarded, so that the append has NO effect whatsoever. To append anitem to d[key] in a way that will affect the persistent mapping, use:data = d[key]data.append(anitem)d[key] = dataTo avoid the problem with mutable entries, you may pass the keywordargument writeback=True in the call to shelve.open. When you use:d = shelve.open(filename, writeback=True)then d keeps a cache of all entries you access, and writes them all backto the persistent mapping when you call d.close(). This ensures thatsuch usage as d[key].append(anitem) works as intended.However, using keyword argument writeback=True may consume vast amountof memory for the cache, and it may make d.close() very slow, if youaccess many of d's entries after opening it in this way: d has no way tocheck which of the entries you access are mutable and/or which ones youactually mutate, so it must cache, and write back at close, all of theentries that you access. You can call d.sync() to write back all theentries in the cache, and empty the cache (d.sync() also synchronizesthe persistent dictionary on disk, if feasible)."""from pickle import Pickler, Unpicklerfrom io import BytesIOimport collections.abc__all__ = ["Shelf", "BsdDbShelf", "DbfilenameShelf", "open"]class _ClosedDict(collections.abc.MutableMapping):'Marker for a closed dict. Access attempts raise a ValueError.'def closed(self, *args):raise ValueError('invalid operation on closed shelf')__iter__ = __len__ = __getitem__ = __setitem__ = __delitem__ = keys = closeddef __repr__(self):return '<Closed Dictionary>'class Shelf(collections.abc.MutableMapping):"""Base class for shelf implementations.This is initialized with a dictionary-like object.See the module's __doc__ string for an overview of the interface."""def __init__(self, dict, protocol=None, writeback=False,keyencoding="utf-8"):self.dict = dictif protocol is None:protocol = 3self._protocol = protocolself.writeback = writebackself.cache = {}self.keyencoding = keyencodingdef __iter__(self):for k in self.dict.keys():yield k.decode(self.keyencoding)def __len__(self):return len(self.dict)def __contains__(self, key):return key.encode(self.keyencoding) in self.dictdef get(self, key, default=None):if key.encode(self.keyencoding) in self.dict:return self[key]return defaultdef __getitem__(self, key):try:value = self.cache[key]except KeyError:f = BytesIO(self.dict[key.encode(self.keyencoding)])value = Unpickler(f).load()if self.writeback:self.cache[key] = valuereturn valuedef __setitem__(self, key, value):if self.writeback:self.cache[key] = valuef = BytesIO()p = Pickler(f, self._protocol)p.dump(value)self.dict[key.encode(self.keyencoding)] = f.getvalue()def __delitem__(self, key):del self.dict[key.encode(self.keyencoding)]try:del self.cache[key]except KeyError:passdef __enter__(self):return selfdef __exit__(self, type, value, traceback):self.close()def close(self):if self.dict is None:returntry:self.sync()try:self.dict.close()except AttributeError:passfinally:# Catch errors that may happen when close is called from __del__# because CPython is in interpreter shutdown.try:self.dict = _ClosedDict()except:self.dict = Nonedef __del__(self):if not hasattr(self, 'writeback'):# __init__ didn't succeed, so don't bother closing# see http://bugs.python.org/issue1339007 for detailsreturnself.close()def sync(self):if self.writeback and self.cache:self.writeback = Falsefor key, entry in self.cache.items():self[key] = entryself.writeback = Trueself.cache = {}if hasattr(self.dict, 'sync'):self.dict.sync()class BsdDbShelf(Shelf):"""Shelf implementation using the "BSD" db interface.This adds methods first(), next(), previous(), last() andset_location() that have no counterpart in [g]dbm databases.The actual database must be opened using one of the "bsddb"modules "open" routines (i.e. bsddb.hashopen, bsddb.btopen orbsddb.rnopen) and passed to the constructor.See the module's __doc__ string for an overview of the interface."""def __init__(self, dict, protocol=None, writeback=False,keyencoding="utf-8"):Shelf.__init__(self, dict, protocol, writeback, keyencoding)def set_location(self, key):(key, value) = self.dict.set_location(key)f = BytesIO(value)return (key.decode(self.keyencoding), Unpickler(f).load())def next(self):(key, value) = next(self.dict)f = BytesIO(value)return (key.decode(self.keyencoding), Unpickler(f).load())def previous(self):(key, value) = self.dict.previous()f = BytesIO(value)return (key.decode(self.keyencoding), Unpickler(f).load())def first(self):(key, value) = self.dict.first()f = BytesIO(value)return (key.decode(self.keyencoding), Unpickler(f).load())def last(self):(key, value) = self.dict.last()f = BytesIO(value)return (key.decode(self.keyencoding), Unpickler(f).load())class DbfilenameShelf(Shelf):"""Shelf implementation using the "dbm" generic dbm interface.This is initialized with the filename for the dbm database.See the module's __doc__ string for an overview of the interface."""def __init__(self, filename, flag='c', protocol=None, writeback=False):import dbmShelf.__init__(self, dbm.open(filename, flag), protocol, writeback)def open(filename, flag='c', protocol=None, writeback=False):"""Open a persistent dictionary for reading and writing.The filename parameter is the base filename for the underlyingdatabase. As a side-effect, an extension may be added to thefilename and more than one file may be created. The optional flagparameter has the same interpretation as the flag parameter ofdbm.open(). The optional protocol parameter specifies theversion of the pickle protocol.See the module's __doc__ string for an overview of the interface."""return DbfilenameShelf(filename, flag, protocol, writeback)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。