[Python-checkins] python/dist/src/Lib shelve.py,1.20,1.21
loewis@users.sourceforge.net
loewis@users.sourceforge.net
Sat, 19 Apr 2003 13:59:04 -0700
Update of /cvsroot/python/python/dist/src/Lib
In directory sc8-pr-cvs1:/tmp/cvs-serv7812/Lib
Modified Files:
shelve.py
Log Message:
Patch #553171: Add writeback parameter. Also add protocol parameter.
Index: shelve.py
===================================================================
RCS file: /cvsroot/python/python/dist/src/Lib/shelve.py,v
retrieving revision 1.20
retrieving revision 1.21
diff -C2 -d -r1.20 -r1.21
*** shelve.py 21 Jan 2003 01:53:09 -0000 1.20
--- shelve.py 19 Apr 2003 20:59:02 -0000 1.21
***************
*** 16,21 ****
d[key] = data # store data at key (overwrites old data if
# using an existing key)
! data = d[key] # retrieve data at key (raise KeyError if no
! # such key)
del d[key] # delete data stored at key (raises KeyError
# if no such key)
--- 16,22 ----
d[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)
***************
*** 27,30 ****
--- 28,58 ----
Dependent on the implementation, closing a persistent dictionary may
or may not be necessary to flush changes to disk.
+
+ Normally, d[key] returns a COPY of the entry. This needs care when
+ mutable 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 persistent
+ mapping -- it only modifies the copy, which is then immediately
+ discarded, so that the append has NO effect whatsoever. To append an
+ item to d[key] in a way that will affect the persistent mapping, use:
+ data = d[key]
+ data.append(anitem)
+ d[key] = data
+
+ To avoid the problem with mutable entries, you may pass the keyword
+ argument 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 back
+ to the persistent mapping when you call d.close(). This ensures that
+ such usage as d[key].append(anitem) works as intended.
+
+ However, using keyword argument writeback=True may consume vast amount
+ of memory for the cache, and it may make d.close() very slow, if you
+ access many of d's entries after opening it in this way: d has no way to
+ check which of the entries you access are mutable and/or which ones you
+ actually mutate, so it must cache, and write back at close, all of the
+ entries that you access. You can call d.sync() to write back all the
+ entries in the cache, and empty the cache (d.sync() also synchronizes
+ the persistent dictionary on disk, if feasible).
"""
***************
*** 42,45 ****
--- 70,74 ----
import UserDict
+ import warnings
__all__ = ["Shelf","BsdDbShelf","DbfilenameShelf","open"]
***************
*** 52,58 ****
"""
! def __init__(self, dict, binary=False):
self.dict = dict
! self._binary = binary
def keys(self):
--- 81,97 ----
"""
! def __init__(self, dict, protocol=None, writeback=False, binary=None):
self.dict = dict
! if protocol is not None and binary is not None:
! raise ValueError, "can't specify both 'protocol' and 'binary'"
! if binary is not None:
! warnings.warn("The 'binary' argument to Shelf() is deprecated",
! PendingDeprecationWarning)
! protocol = int(binary)
! if protocol is None:
! protocol = 0
! self._protocol = protocol
! self.writeback = writeback
! self.cache = {}
def keys(self):
***************
*** 74,83 ****
def __getitem__(self, key):
! f = StringIO(self.dict[key])
! return Unpickler(f).load()
def __setitem__(self, key, value):
f = StringIO()
! p = Pickler(f, self._binary)
p.dump(value)
self.dict[key] = f.getvalue()
--- 113,130 ----
def __getitem__(self, key):
! try:
! value = self.cache[key]
! except KeyError:
! f = StringIO(self.dict[key])
! value = Unpickler(f).load()
! if self.writeback:
! self.cache[key] = value
! return value
def __setitem__(self, key, value):
+ if self.writeback:
+ self.cache[key] = value
f = StringIO()
! p = Pickler(f, self._protocol)
p.dump(value)
self.dict[key] = f.getvalue()
***************
*** 85,90 ****
--- 132,142 ----
def __delitem__(self, key):
del self.dict[key]
+ try:
+ del self.cache[key]
+ except KeyError:
+ pass
def close(self):
+ self.sync()
try:
self.dict.close()
***************
*** 97,100 ****
--- 149,158 ----
def sync(self):
+ if self.writeback and self.cache:
+ self.writeback = False
+ for key, entry in self.cache.iteritems():
+ self[key] = entry
+ self.writeback = True
+ self.cache = {}
if hasattr(self.dict, 'sync'):
self.dict.sync()
***************
*** 114,119 ****
"""
! def __init__(self, dict, binary=False):
! Shelf.__init__(self, dict, binary)
def set_location(self, key):
--- 172,177 ----
"""
! def __init__(self, dict, protocol=None, writeback=False, binary=None):
! Shelf.__init__(self, dict, protocol, writeback, binary)
def set_location(self, key):
***************
*** 150,170 ****
"""
! def __init__(self, filename, flag='c', binary=False):
import anydbm
! Shelf.__init__(self, anydbm.open(filename, flag), binary)
! def open(filename, flag='c', binary=False):
"""Open a persistent dictionary for reading and writing.
! The filename parameter is the base filename for the underlying database.
! As a side-effect, an extension may be added to the filename and more
! than one file may be created. The optional flag parameter has the
! same interpretation as the flag parameter of anydbm.open(). The
! optional binary parameter may be set to True to force the use of binary
! pickles for serializing data values.
See the module's __doc__ string for an overview of the interface.
"""
! return DbfilenameShelf(filename, flag, binary)
--- 208,231 ----
"""
! def __init__(self, filename, flag='c', protocol=None, writeback=False, binary=None):
import anydbm
! Shelf.__init__(self, anydbm.open(filename, flag), protocol, writeback, binary)
! def open(filename, flag='c', protocol=None, writeback=False, binary=None):
"""Open a persistent dictionary for reading and writing.
! The filename parameter is the base filename for the underlying
! database. As a side-effect, an extension may be added to the
! filename and more than one file may be created. The optional flag
! parameter has the same interpretation as the flag parameter of
! anydbm.open(). The optional protocol parameter specifies the
! version of the pickle protocol (0, 1, or 2).
!
! The optional binary parameter is deprecated and may be set to True
! to force the use of binary pickles for serializing data values.
See the module's __doc__ string for an overview of the interface.
"""
! return DbfilenameShelf(filename, flag, binary, writeback)