Download presentation
Presentation is loading. Please wait.
Published byVanessa McConnell Modified over 11 years ago
1
Writing persistent classes Persistent if reachable from the root Persistency by storing/loading pickles ZODB must know when an object is accessed or changed Automatic (transparent) for attribute access Some common Python idioms require explicit interactions
2
Persistence by reachability Persistent object must be reachable from the root object, which ZODB creates automatically myPersistentObj = PersistentObj() conn.root()[coll] = myPersistentObject
3
Saved state is a pickle Objects to be stored in ZODB must be picklable. Normally, an objects attributes (__dict__) are pickled by ZODB for storing, and the pickle is unserialized into __dict__ for loading. Persistent captures all attribute access via __getattr__() and __setattr__() hooks
4
Subobjects Subobjects are pickled by value, except: –if they are Persistent, theyre pickled by persistent id –Classes, modules, and functions are pickled by fully qualified name –Upon unpickling instances, __init__() is not called unless the class defines an __getinitargs__() method. –See the Python 2.2 docs for pickle module for more rules regarding extension types, etc.
5
Mutable attributes Object has an attribute thats a mutable Python object, e.g. dictionary or list Changes to the mutable object are not caught by ZODB, so you have to help it out >>> person.appointments [] >>> person.appointments.append(app) >>> person._p_changed = 1
6
PersistentMapping Class provided by ZODB for persistent, near-dictionary-like semantics It fiddles with _p_changed for you: >>> person.contacts >>> person.contacts[Barry] = barry >>> get_transaction().commit()
7
PersistentList? Not part of Zope Corps distribution (yet) Andrew Kuchlings SourceForge project has one (zodb.sf.net) Provides list-like semantics while taking care of _p_changed fiddling
8
Unpicklable objects class F(Persistent): def __init__(self, filename): self.fp = open(filename) >>> root[files] = F(/etc/passwd) >>> get_transaction().commit() … cPickle.UnpicklableError: cannot pickle objects
9
Unpicklable objects class F(Persistent): def __init__(self, filename): self.fp = open(filename) def __getstate__(self): return self.fp.name def __setstate__(self, filename): self.fp = open(filename) >>> root[files] = F(/etc/passwd) >>> get_transaction().commit() >>>
10
Volatile attributes Attributes not to be stored persistently should be prefixed with _v_ class F(Persistent): def __init__(self, filename): self._v_fp = open(filename) >>> root[files] = F(/etc/passwd) >>> get_transaction().commit() # later… >>> root[files].__dict__ {}
11
Python special methods Persistent classes cant define reversed binary operators like __radd__ and __rsub__ Older versions had some problems with __cmp__() and (maybe) __hash__() Persistent classes wont track new __ methods introduced in Python 2.2 and beyond.
12
Managing object evolution Classes can change by adding, deleting, or redefining methods, or adding and deleting attributes. Changes to methods just work because classes are stored by reference, not by value Changes to attributes can be handled by __setstate__() method, or by off-line update script
13
__setstate__() class Person(Persistent): def __init__(self, name): self.name = name >>> barry = Person(Barry Warsaw) >>> root[people][barry] = barry >>> get_transaction().commit()
14
__setstate__() cont class Person(Persistent): def __init__(self, username, realname): self.username = username self.realname = realname def __setstate__(self, d): self.realname = name = d[name] username = name.split()[0].lower() self.username = username
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.