summaryrefslogtreecommitdiffstats
path: root/Doc/includes
diff options
context:
space:
mode:
authorAlexandre Vassalotti <alexandre@peadrop.com>2008-10-18 20:47:58 (GMT)
committerAlexandre Vassalotti <alexandre@peadrop.com>2008-10-18 20:47:58 (GMT)
commit5f3b63ad6f85bfe162a637d2b7fd8f3a3245b0e2 (patch)
treecd65f37f7663da5a590d9eaf728ee0d15381c155 /Doc/includes
parent758bca6e36167075fb41a2fc671665506ef0fe0e (diff)
downloadcpython-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.py88
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()