Online Book Reader

Home Category

Learning Python - Mark Lutz [371]

By Root 1779 0
db = shelve.open('persondb') # Reopen the shelve

>>> len(db) # Three 'records' stored

3

>>> list(db.keys()) # keys is the index

['Tom Jones', 'Sue Jones', 'Bob Smith'] # list to make a list in 3.0

>>> bob = db['Bob Smith'] # Fetch bob by key

>>> print(bob) # Runs __str__ from AttrDisplay

[Person: job=None, name=Bob Smith, pay=0]

>>> bob.lastName() # Runs lastName from Person

'Smith'

>>> for key in db: # Iterate, fetch, print

print(key, '=>', db[key])

Tom Jones => [Manager: job=mgr, name=Tom Jones, pay=50000]

Sue Jones => [Person: job=dev, name=Sue Jones, pay=100000]

Bob Smith => [Person: job=None, name=Bob Smith, pay=0]

>>> for key in sorted(db):

print(key, '=>', db[key]) # Iterate by sorted keys

Bob Smith => [Person: job=None, name=Bob Smith, pay=0]

Sue Jones => [Person: job=dev, name=Sue Jones, pay=100000]

Tom Jones => [Manager: job=mgr, name=Tom Jones, pay=50000]

Notice that we don’t have to import our Person or Manager classes here in order to load or use our stored objects. For example, we can call bob’s lastName method freely, and get his custom print display format automatically, even though we don’t have his Person class in our scope here. This works because when Python pickles a class instance, it records its self instance attributes, along with the name of the class it was created from and the module where the class lives. When bob is later fetched from the shelve and unpickled, Python will automatically reimport the class and link bob to it.

The upshot of this scheme is that class instances automatically acquire all their class behavior when they are loaded in the future. We have to import our classes only to make new instances, not to process existing ones. Although a deliberate feature, this scheme has somewhat mixed consequences:

The downside is that classes and their module’s files must be importable when an instance is later loaded. More formally, pickleable classes must be coded at the top level of a module file accessible from a directory listed on the sys.path module search path (and shouldn’t live in the most script files’ module __main__ unless they’re always in that module when used). Because of this external module file requirement, some applications choose to pickle simpler objects such as dictionaries or lists, especially if they are to be transferred across the Internet.

The upside is that changes in a class’s source code file are automatically picked up when instances of the class are loaded again; there is often no need to update stored objects themselves, since updating their class’s code changes their behavior.

Shelves also have well-known limitations (the database suggestions at the end of this chapter mention a few of these). For simple object storage, though, shelves and pickles are remarkably easy-to-use tools.

Updating Objects on a Shelve

Now for one last script: let’s write a program that updates an instance (record) each time it runs, to prove the point that our objects really are persistent (i.e., that their current values are available every time a Python program runs). The following file, updatedb.py, prints the database and gives a raise to one of our stored objects each time. If you trace through what’s going on here, you’ll notice that we’re getting a lot of utility “for free”—printing our objects automatically employs the general __str__ overloading method, and we give raises by calling the giveRaise method we wrote earlier. This all “just works” for objects based on OOP’s inheritance model, even when they live in a file:

# File updatedb.py: update Person object on database

import shelve

db = shelve.open('persondb') # Reopen shelve with same filename

for key in sorted(db): # Iterate to display database objects

print(key, '\t=>', db[key]) # Prints with custom format

sue = db['Sue Jones'] # Index by key to fetch

sue.giveRaise(.10) # Update in memory using class method

db['Sue Jones'] = sue # Assign to key to update in shelve

db.close() # Close after making changes

Because this script prints the database when

Return Main Page Previous Page Next Page

®Online Book Reader