diff options
author | Alexandre Vassalotti <alexandre@peadrop.com> | 2008-10-18 20:47:58 (GMT) |
---|---|---|
committer | Alexandre Vassalotti <alexandre@peadrop.com> | 2008-10-18 20:47:58 (GMT) |
commit | 5f3b63ad6f85bfe162a637d2b7fd8f3a3245b0e2 (patch) | |
tree | cd65f37f7663da5a590d9eaf728ee0d15381c155 /Doc/includes | |
parent | 758bca6e36167075fb41a2fc671665506ef0fe0e (diff) | |
download | cpython-5f3b63ad6f85bfe162a637d2b7fd8f3a3245b0e2.zip cpython-5f3b63ad6f85bfe162a637d2b7fd8f3a3245b0e2.tar.gz cpython-5f3b63ad6f85bfe162a637d2b7fd8f3a3245b0e2.tar.bz2 |
Improve pickle's documentation.
Use double-space for ending a sentence.
Add dbpickle.py example.
Improve description about persistent IDs.
Diffstat (limited to 'Doc/includes')
-rw-r--r-- | Doc/includes/dbpickle.py | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/Doc/includes/dbpickle.py b/Doc/includes/dbpickle.py new file mode 100644 index 0000000..d2eee6c --- /dev/null +++ b/Doc/includes/dbpickle.py @@ -0,0 +1,88 @@ +# Simple example presenting how persistent ID can be used to pickle +# external objects by reference. + +import pickle +import sqlite3 +from collections import namedtuple + +# Simple class representing a record in our database. +MemoRecord = namedtuple("MemoRecord", "key, task") + +class DBPickler(pickle.Pickler): + + def persistent_id(self, obj): + # Instead of pickling MemoRecord as a regular class instance, we emit a + # persistent ID instead. + if isinstance(obj, MemoRecord): + # Here, our persistent ID is simply a tuple containing a tag and a + # key which refers to a specific record in the database. + return ("MemoRecord", obj.key) + else: + # If obj does not have a persistent ID, return None. This means obj + # needs to be pickled as usual. + return None + + +class DBUnpickler(pickle.Unpickler): + + def __init__(self, file, connection): + super().__init__(file) + self.connection = connection + + def persistent_load(self, pid): + # This method is invoked whenever a persistent ID is encountered. + # Here, pid is the tuple returned by DBPickler. + cursor = self.connection.cursor() + type_tag, key_id = pid + if type_tag == "MemoRecord": + # Fetch the referenced record from the database and return it. + cursor.execute("SELECT * FROM memos WHERE key=?", (str(key_id),)) + key, task = cursor.fetchone() + return MemoRecord(key, task) + else: + # Always raises an error if you cannot return the correct object. + # Otherwise, the unpickler will think None is the object referenced + # by the persistent ID. + raise pickle.UnpicklingError("unsupported persistent object") + + +def main(verbose=True): + import io, pprint + + # Initialize and populate our database. + conn = sqlite3.connect(":memory:") + cursor = conn.cursor() + cursor.execute("CREATE TABLE memos(key INTEGER PRIMARY KEY, task TEXT)") + tasks = ( + 'give food to fish', + 'prepare group meeting', + 'fight with a zebra', + ) + for task in tasks: + cursor.execute("INSERT INTO memos VALUES(NULL, ?)", (task,)) + + # Fetch the records to be pickled. + cursor.execute("SELECT * FROM memos") + memos = [MemoRecord(key, task) for key, task in cursor] + # Save the records using our custom DBPickler. + file = io.BytesIO() + DBPickler(file).dump(memos) + + if verbose: + print("Records to be pickled:") + pprint.pprint(memos) + + # Update a record, just for good measure. + cursor.execute("UPDATE memos SET task='learn italian' WHERE key=1") + + # Load the reports from the pickle data stream. + file.seek(0) + memos = DBUnpickler(file, conn).load() + + if verbose: + print("Unpickled records:") + pprint.pprint(memos) + + +if __name__ == '__main__': + main() |