Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3bf99e3

Browse files
author
Skip Montanaro
committed
Add support for binary pickles to the shelve module. In some situations
this can result in significantly smaller files. All classes as well as the open function now accept an optional binary parameter, which defaults to False for backward compatibility. Added a small test suite, updated the libref documentation (including documenting the exported classes and fixing a few other nits) and added a note about the change to Misc/NEWS.
1 parent ea7f75d commit 3bf99e3

4 files changed

Lines changed: 98 additions & 12 deletions

File tree

Doc/lib/libshelve.tex

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ \section{\module{shelve} ---
1919
\begin{verbatim}
2020
import shelve
2121
22-
d = shelve.open(filename) # open, with (g)dbm filename -- no suffix
22+
d = shelve.open(filename) # open -- file may get suffix added by low-level
23+
# library
2324
2425
d[key] = data # store data at key (overwrites old data if
2526
# using an existing key)
@@ -54,8 +55,10 @@ \section{\module{shelve} ---
5455
\refbimodindex{gdbm}
5556

5657
\item
57-
Dependent on the implementation, closing a persistent dictionary may
58-
or may not be necessary to flush changes to disk.
58+
Depending on the implementation, closing a persistent dictionary may
59+
or may not be necessary to flush changes to disk. The \method{__del__}
60+
method of the \class{Shelf} class calls the \method{close} method, so the
61+
programmer generally need not do this explicitly.
5962

6063
\item
6164
The \module{shelve} module does not support \emph{concurrent} read/write
@@ -67,10 +70,37 @@ \section{\module{shelve} ---
6770

6871
\end{itemize}
6972

73+
\begin{classdesc}{Shelf}{dict\optional{, binary=False}}
74+
A subclass of \class{UserDict.DictMixin} which stores pickled values in the
75+
\var{dict} object. If the \var{binary} parameter is \constant{True}, binary
76+
pickles will be used. This can provide much more compact storage than plain
77+
text pickles, depending on the nature of the objects stored in the databse.
78+
\end{classdesc}
79+
80+
\begin{classdesc}{BsdDbShelf}{dict\optional{, binary=False}}
81+
A subclass of \class{Shelf} which exposes \method{first}, \method{next},
82+
{}\method{previous}, \method{last} and \method{set_location} which are
83+
available in the \module{bsddb} module but not in other database modules.
84+
The \var{dict} object passed to the constructor must support those methods.
85+
This is generally accomplished by calling one of \function{bsddb.hashopen},
86+
\function{bsddb.btopen} or \function{bsddb.rnopen}. The optional
87+
\var{binary} parameter has the same interpretation as for the \class{Shelf}
88+
class.
89+
\end{classdesc}
90+
91+
\begin{classdesc}{DbfilenameShelf}{dict\optional{, flag='c'}\optional{, binary=False}}
92+
A subclass of \class{Shelf} which accepts a filename instead of a dict-like
93+
object. The underlying file will be opened using \function{anydbm.open}.
94+
By default, the file will be created and opened for both read and write.
95+
The optional \var{binary} parameter has the same interpretation as for the
96+
\class{Shelf} class.
97+
\end{classdesc}
7098

7199
\begin{seealso}
72100
\seemodule{anydbm}{Generic interface to \code{dbm}-style databases.}
73-
\seemodule{dbhash}{BSD \code{db} database interface.}
101+
\seemodule{bsddb}{BSD \code{db} database interface.}
102+
\seemodule{dbhash}{Thin layer around the \module{bsddb} which provides an
103+
\function{open} function like the other database modules.}
74104
\seemodule{dbm}{Standard \UNIX{} database interface.}
75105
\seemodule{dumbdbm}{Portable implementation of the \code{dbm} interface.}
76106
\seemodule{gdbm}{GNU database interface, based on the \code{dbm} interface.}

Lib/shelve.py

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ class Shelf(UserDict.DictMixin):
5151
See the module's __doc__ string for an overview of the interface.
5252
"""
5353

54-
def __init__(self, dict):
54+
def __init__(self, dict, binary=False):
5555
self.dict = dict
56+
self.binary = binary
5657

5758
def keys(self):
5859
return self.dict.keys()
@@ -77,7 +78,7 @@ def __getitem__(self, key):
7778

7879
def __setitem__(self, key, value):
7980
f = StringIO()
80-
p = Pickler(f)
81+
p = Pickler(f, self.binary)
8182
p.dump(value)
8283
self.dict[key] = f.getvalue()
8384

@@ -112,8 +113,8 @@ class BsdDbShelf(Shelf):
112113
See the module's __doc__ string for an overview of the interface.
113114
"""
114115

115-
def __init__(self, dict):
116-
Shelf.__init__(self, dict)
116+
def __init__(self, dict, binary=False):
117+
Shelf.__init__(self, dict, binary)
117118

118119
def set_location(self, key):
119120
(key, value) = self.dict.set_location(key)
@@ -148,16 +149,16 @@ class DbfilenameShelf(Shelf):
148149
See the module's __doc__ string for an overview of the interface.
149150
"""
150151

151-
def __init__(self, filename, flag='c'):
152+
def __init__(self, filename, flag='c', binary=False):
152153
import anydbm
153-
Shelf.__init__(self, anydbm.open(filename, flag))
154+
Shelf.__init__(self, anydbm.open(filename, flag), binary)
154155

155156

156-
def open(filename, flag='c'):
157+
def open(filename, flag='c', binary=False):
157158
"""Open a persistent dictionary for reading and writing.
158159
159160
Argument is the filename for the dbm database.
160161
See the module's __doc__ string for an overview of the interface.
161162
"""
162163

163-
return DbfilenameShelf(filename, flag)
164+
return DbfilenameShelf(filename, flag, binary)

Lib/test/test_shelve.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import os
2+
import unittest
3+
import shelve
4+
import glob
5+
from test import test_support
6+
7+
class TestCase(unittest.TestCase):
8+
9+
fn = "shelftemp.db"
10+
11+
def test_ascii_file_shelf(self):
12+
try:
13+
s = shelve.open(self.fn, binary=False)
14+
s['key1'] = (1,2,3,4)
15+
self.assertEqual(s['key1'], (1,2,3,4))
16+
s.close()
17+
finally:
18+
for f in glob.glob(self.fn+"*"):
19+
os.unlink(f)
20+
21+
def test_binary_file_shelf(self):
22+
try:
23+
s = shelve.open(self.fn, binary=True)
24+
s['key1'] = (1,2,3,4)
25+
self.assertEqual(s['key1'], (1,2,3,4))
26+
s.close()
27+
finally:
28+
for f in glob.glob(self.fn+"*"):
29+
os.unlink(f)
30+
31+
def test_in_memory_shelf(self):
32+
d1 = {}
33+
s = shelve.Shelf(d1, binary=False)
34+
s['key1'] = (1,2,3,4)
35+
self.assertEqual(s['key1'], (1,2,3,4))
36+
s.close()
37+
d2 = {}
38+
s = shelve.Shelf(d2, binary=True)
39+
s['key1'] = (1,2,3,4)
40+
self.assertEqual(s['key1'], (1,2,3,4))
41+
s.close()
42+
43+
self.assertEqual(len(d1), 1)
44+
self.assertNotEqual(d1, d2)
45+
46+
def test_main():
47+
test_support.run_unittest(TestCase)
48+
49+
50+
if __name__ == "__main__":
51+
test_main()

Misc/NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,10 @@ Library
440440
all dictionary methods. This eases the transition to persistent
441441
storage for scripts originally written with dictionaries in mind.
442442

443+
- shelve.open and the various classes in shelve.py now accept an optional
444+
binary flag, which defaults to False. If True, the values stored in the
445+
shelf are binary pickles.
446+
443447
- A new package, logging, implements the logging API defined by PEP
444448
282. The code is written by Vinay Sajip.
445449

0 commit comments

Comments
 (0)