Learning Python - Mark Lutz [370]
from person import Person # Load class with from
bob = Person(...) # Use name directly
We’ll use from to load in our script, just because it’s a bit less to type. Copy or retype this code to make instances of our classes in the new script, so we have something to store (this is a simple demo, so we won’t worry about the test-code redundancy here). Once we have some instances, it’s almost trivial to store them on a shelve. We simply import the shelve module, open a new shelve with an external filename, assign the objects to keys in the shelve, and close the shelve when we’re done because we’ve made changes:
# File makedb.py: store Person objects on a shelve database
from person import Person, Manager # Load our classes
bob = Person('Bob Smith') # Re-create objects to be stored
sue = Person('Sue Jones', job='dev', pay=100000)
tom = Manager('Tom Jones', 50000)
import shelve
db = shelve.open('persondb') # Filename where objects are stored
for object in (bob, sue, tom): # Use object's name attr as key
db[object.name] = object # Store object on shelve by key
db.close() # Close after making changes
Notice how we assign objects to the shelve using their own names as keys. This is just for convenience; in a shelve, the key can be any string, including one we might create to be unique using tools such as process IDs and timestamps (available in the os and time standard library modules). The only rule is that the keys must be strings and should be unique, since we can store just one object per key (though that object can be a list or dictionary containing many objects). The values we store under keys, though, can be Python objects of almost any sort: built-in types like strings, lists, and dictionaries, as well as user-defined class instances, and nested combinations of all of these.
That’s all there is to it—if this script has no output when run, it means it probably worked; we’re not printing anything, just creating and storing objects:
C:\misc> makedb.py
Exploring Shelves Interactively
At this point, there are one or more real files in the current directory whose names all start with “persondb”. The actual files created can vary per platform, and just like in the built-in open function, the filename in shelve.open() is relative to the current working directory unless it includes a directory path. Wherever they are stored, these files implement a keyed-access file that contains the pickled representation of our three Python objects. Don’t delete these files—they are your database, and are what you’ll need to copy or transfer when you back up or move your storage.
You can look at the shelve’s files if you want to, either from Windows Explorer or the Python shell, but they are binary hash files, and most of their content makes little sense outside the context of the shelve module. With Python 3.0 and no extra software installed, our database is stored in three files (in 2.6, it’s just one file, persondb, because the bsddb extension module is preinstalled with Python for shelves; in 3.0, bsddb is a third-party open source add-on):
# Directory listing module: verify files are present
>>> import glob
>>> glob.glob('person*')
['person.py', 'person.pyc', 'persondb.bak', 'persondb.dat', 'persondb.dir']
# Type the file: text mode for string, binary mode for bytes
>>> print(open('persondb.dir').read())
'Tom Jones', (1024, 91)
...more omitted...
>>> print(open('persondb.dat', 'rb').read())
b'\x80\x03cperson\nPerson\nq\x00)\x81q\x01}q\x02(X\x03\x00\x00\x00payq\x03K...
...more omitted...
This content isn’t impossible to decipher, but it can vary on different platforms and doesn’t exactly qualify as a user-friendly database interface! To verify our work better, we can write another script, or poke around our shelve at the interactive prompt. Because shelves are Python objects containing Python objects, we can process them with normal Python syntax and development modes. Here, the interactive prompt effectively becomes a database client:
>>> import shelve
>>>