from that module using the original class name. If the module or class has been
moved or renamed, it might not be found.
In applications where pickled objects are shipped over network sockets, it’s pos-
sible to satisfy this constraint by shipping the text of the class along with stored
instances; recipients may simply store the class in a local module file on the import
search path prior to unpickling received instances. Where this is inconvenient or
impossible, simpler pickled objects such as lists and dictionaries with nesting may
be transferred instead, as they require no source file to be reconstructed.
Class changes must be backward compatible
Although Python lets you change a class while instances of it are stored on a shelve,
those changes must be backward compatible with the objects already stored. For
instance, you cannot change the class to expect an attribute not associated with
already stored persistent instances unless you first manually update those stored
instances or provide extra conversion protocols on the class.
Other pickle module constraints
Shelves also inherit the pickling systems’ nonclass limitations. As discussed earlier,
some types of objects (e.g., open files and sockets) cannot be pickled, and thus
cannot be stored in a shelve.
In an early Python release, persistent object classes also had to either use constructors
with no arguments or provide defaults for all constructor arguments (much like the
notion of a C++ copy constructor). This constraint was dropped as of Python 1.5.2—
classes with nondefaulted constructor arguments now work as is in the pickling system.*
Other Shelve Limitations
Finally, although shelves store objects persistently, they are not really object-oriented
database systems. Such systems also implement features such as immediate automatic
write-through on changes, transaction commits and rollbacks, safe concurrent updates,
and object decomposition and delayed (“lazy”) component fetches based on generated
object IDs. Parts of larger objects may be loaded into memory only as they are accessed.
It’s possible to extend shelves to support such features manually, but you don’t need
to—the ZODB system, among others, provides an implementation of a more complete
object-oriented database system. It is constructed on top of Python’s built-in pickling
- Interestingly, Python avoids calling the class to re-create a pickled instance and instead simply makes a class
object generically, inserts instance attributes, and sets the instance’s class pointer to the original class
directly. This avoids the need for defaults, but it also means that the class init constructors that are no
longer called as objects are unpickled, unless you provide extra methods to force the call. See the library
manual for more details, and see the pickle module’s source code (pickle.py in the source library) if you’re
curious about how this works. Or see the PyForm example later in this chapter—it does something very
similar with class links to build an instance object from a class and dictionary of attributes, without
calling the class’s init constructor. This makes constructor argument defaults unnecessary in classes
used for records browsed by PyForm, but it’s the same idea.
1324 | Chapter 17: Databases and Persistence