''' Shelve_test2.py
use a dictionary object and module shelve
to create a 'persistent to file' dictionary

Python2 creates a single (24kb) file 'phonebook.slv'
Python3 creates 3 much smaller (about 1kb each) files:
  'phonebook.slv.dir'
  'phonebook.slv.dat'
  'phonebook.slv.bak'

Tested with Python27 and Python33  by vegaseat  04sep2013
'''

import shelve

# name shelve byte stream data file
# works with Python2 annd Python3
data_file = 'phonebook.slv'

# open existing shelve file or create new shelve file
sh = shelve.open(data_file)

# a simple dictionary of name:phone pairs
phonebook = {
'Andrew Parson': '880-6336',
'Emily Everett': '678-4346', 
'Peter Power': '765-8344',
'Lewis Lame': '112-2345'
}

# this will save all current phonebook data 
# the access key will be "myphone_dict" (you pick name)
sh["myphone_dict"] = phonebook

# do one more dictionary entry ...
phonebook['Ginger Roger'] = '123-4567'
# you can update and save again before you close
sh["myphone_dict"] = phonebook
# close when done
sh.close()

# testing ...
# open the shelve file again for further work
# remember the access key is "myphone_dict"
sh = shelve.open(data_file)
phonebook2 = sh["myphone_dict"]

# can add another dictionary entry
phonebook2['Larry Lark'] = '923-4568'

# save the current phonebook data to the shelve file 
sh["myphone_dict"] = phonebook2
# close when done
sh.close()

print('-'*30)

# test the contents ...
# retrieve the saved data from the file
sh = shelve.open('phonebook.slv')
phonebook3 = sh["myphone_dict"]

# print the contents
for name, phone in sorted(phonebook3.items()):
    print( "%-20s  %s" % (name, phone) )

print('-'*30)

# close when done
sh.close()

''' result ...
------------------------------
Andrew Parson         880-6336
Emily Everett         678-4346
Ginger Roger          123-4567
Larry Lark            923-4568
Lewis Lame            112-2345
Peter Power           765-8344
------------------------------
'''
2
Contributors
2
Replies
81
Views
4 Years
Discussion Span
Last Post by Gribouillis
0

For the sake of comparing tools, here is the same code written with the well known zodb module instead of shelve.

''' zodb_test.py
Use third party module ZODB (zope object database)
to create a 'persistent to file' dictionary

Python 2 and 3 create files
    'phonebook.fs'
    'phonebook.fs.index'
    'phonebook.fs.lock'
    'phonebook.fs.tmp'
The files are not compatible between Python 2 and 3.

Tested with Python27 and Python33 by Gribouillis 2013-Sep-05
'''

# There are a few more necessary imports with zodb
from ZODB.FileStorage import FileStorage
from ZODB.DB import DB
import transaction
from BTrees.OOBTree import OOBTree

# name zodb data file
data_file = 'phonebook.fs'

# open existing zodb storage file or create new file
storage = FileStorage(data_file)
db = DB(storage)
connection = db.open()
sh = connection.root() # <- our starting point, the database root object.

# create a persistent dictionary (technically a b-tree)
phonebook = sh["myphone_dict"] = OOBTree()

# update from an ordinary python dictionary
phonebook.update({
'Andrew Parson': '880-6336',
'Emily Everett': '678-4346', 
'Peter Power': '765-8344',
'Lewis Lame': '112-2345'
})

# do one more dictionary entry ...
phonebook['Ginger Roger'] = '123-4567'

# save to database before you close
transaction.commit()

# close when done. A few more calls than with shelves.
connection.close()
db.close()
storage.close()

# testing ...
# open the zodb file again for further work
# remember the access key is "myphone_dict"
storage = FileStorage(data_file)
db = DB(storage)
connection = db.open()
sh = connection.root()

phonebook2 = sh["myphone_dict"]

# can add another dictionary entry
phonebook2['Larry Lark'] = '923-4568'

# save before you close
transaction.commit()

# close when done
connection.close()
db.close()
storage.close()

print('-'*30)

# test the contents ...
# retrieve the saved data from the file
storage = FileStorage(data_file)
db = DB(storage)
connection = db.open()
sh = connection.root()

phonebook3 = sh["myphone_dict"]

# print the contents
for name, phone in sorted(phonebook3.items()):
    print( "%-20s  %s" % (name, phone) )

print('-'*30)

# close when done
connection.close()
db.close()
storage.close()

''' result ...
------------------------------
Andrew Parson         880-6336
Emily Everett         678-4346
Ginger Roger          123-4567
Larry Lark            923-4568
Lewis Lame            112-2345
Peter Power           765-8344
------------------------------
'''

Next step: comparative benchmarks :). Notice that zodb does not load the whole dictionary when it is accessed, because we chose the OOBTree class. It is suitable for very large data sets.

Edited by Gribouillis

Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.