Commit b898b1ed authored by Fred Drake's avatar Fred Drake

Remove old output; this is moving to a different location.

parent 8e329f60
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="previous" HREF="node39.html">
<LINK REL="up" HREF="zodb.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="About this document ...">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>About this document ...</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node51.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node51.html">ADDENDUM: How to use</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H1><A NAME="SECTION000900000000000000000">
About this document ...</A>
</H1>
<strong>ZODB/ZEO Programming Guide</strong>,
17 January 2003, Release 0.04
<p> This document was generated using the <a
href="http://saftsack.fs.uni-bayreuth.de/~latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> translator.
</p>
<p> <a
href="http://saftsack.fs.uni-bayreuth.de/~latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> is Copyright &copy;
1993, 1994, 1995, 1996, 1997, <a
href="http://cbl.leeds.ac.uk/nikos/personal.html">Nikos
Drakos</a>, Computer Based Learning Unit, University of
Leeds, and Copyright &copy; 1997, 1998, <a
href="http://www.maths.mq.edu.au/~ross/">Ross
Moore</a>, Mathematics Department, Macquarie University,
Sydney.
</p>
<p> The application of <a
href="http://saftsack.fs.uni-bayreuth.de/~latex2ht/">
<strong>LaTeX</strong>2<tt>HTML</tt></a> to the Python
documentation has been heavily tailored by Fred L. Drake,
Jr. Original navigation icons were contributed by Christopher
Petrilli.
</p>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node51.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node51.html">ADDENDUM: How to use</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node2.html">
<LINK REL="previous" HREF="zodb.html">
<LINK REL="up" HREF="zodb.html">
<LINK REL="next" HREF="node2.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="Contents">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>Contents</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="zodb.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node2.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node2.html">1 Introduction</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<BR>
<BR><H2><A NAME="SECTION000100000000000000000">
Contents</A>
</H2>
<!--Table of Contents-->
<UL CLASS="TofC">
<LI><A href="node2.html">1 Introduction</a>
<UL>
<LI><A href="node3.html">1.1 What is the ZODB?</a>
<LI><A href="node4.html">1.2 OODBs vs. Relational DBs</a>
<LI><A href="node5.html">1.3 What is ZEO?</a>
<LI><A href="node6.html">1.4 About this guide</a>
<LI><A href="node7.html">1.5 Acknowledgements</a>
</ul>
<LI><A href="node8.html">2 ZODB Programming</a>
<UL>
<LI><A href="node9.html">2.1 Installing ZODB</a>
<LI><A href="node12.html">2.2 How ZODB Works</a>
<LI><A href="node13.html">2.3 Opening a ZODB</a>
<LI><A href="node14.html">2.4 Writing a Persistent Class</a>
<LI><A href="node15.html">2.5 Rules for Writing Persistent Classes</a>
<LI><A href="node19.html">2.6 Writing Persistent Classes</a>
</ul>
<LI><A href="zeo.html">3 ZEO</a>
<UL>
<LI><A href="node22.html">3.1 How ZEO Works</a>
<LI><A href="node23.html">3.2 Installing ZEO</a>
<LI><A href="node26.html">3.3 Testing the ZEO Installation</a>
<LI><A href="node27.html">3.4 ZEO Programming Notes</a>
<LI><A href="node28.html">3.5 Sample Application: chatter.py</a>
</ul>
<LI><A href="node29.html">4 Transactions and Versioning</a>
<UL>
<LI><A href="node30.html">4.1 Subtransactions</a>
<LI><A href="node31.html">4.2 Undoing Changes</a>
<LI><A href="node32.html">4.3 Versions</a>
<LI><A href="node33.html">4.4 Multithreaded ZODB Programs</a>
</ul>
<LI><A href="node34.html">5 Related Modules</a>
<UL>
<LI><A href="node35.html">5.1 ZODB.PersistentMapping</a>
<LI><A href="node36.html">5.2 ZODB.PersistentList</a>
<LI><A href="node37.html">5.3 BTrees Package</a>
</ul>
<LI><A href="node38.html">A. Resources</a>
<LI><A href="node39.html">B. GNU Free Documentation License</a>
<UL>
<LI><A href="node40.html">Preamble</a>
<LI><A href="node41.html">B..1 Applicability and Definitions</a>
<LI><A href="node42.html">B..2 Verbatim Copying</a>
<LI><A href="node43.html">B..3 Copying in Quantity</a>
<LI><A href="node44.html">B..4 Modifications</a>
<LI><A href="node45.html">B..5 Combining Documents</a>
<LI><A href="node46.html">B..6 Collections of Documents</a>
<LI><A href="node47.html">B..7 Aggregation With Independent Works</a>
<LI><A href="node48.html">B..8 Translation</a>
<LI><A href="node49.html">B..9 Termination</a>
<LI><A href="node50.html">B..10 Future Revisions of This Licence</a>
<LI><A href="node51.html">ADDENDUM: How to use this License for your documents</a>
</ul>
<LI><A href="about.html">About this document ...</a>
</ul>
<!--End of Table of Contents-->
<P>
&#169;Copyright 2002 A.M. Kuchling.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1
or any later version published by the Free Software Foundation;
with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
A copy of the license is included in the appendix entitled ``GNU
Free Documentation License''.
<P>
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="zodb.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node2.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node2.html">1 Introduction</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
\batchmode
\documentclass{howto}
\RequirePackage{ifthen}
\title{ZODB/ZEO Programming Guide}
\release{0.04}
\date{\today}
\author{A.M.\ Kuchling}\authoraddress{akuchlin@mems-exchange.org}
\usepackage[dvips]{color}
\pagecolor[gray]{.7}
\usepackage[latin1]{inputenc}
\makeatletter
\makeatletter
\count@=\the\catcode`\_ \catcode`\_=8
\newenvironment{tex2html_wrap}{}{}%
\catcode`\<=12\catcode`\_=\count@
\newcommand{\providedcommand}[1]{\expandafter\providecommand\csname #1\endcsname}%
\newcommand{\renewedcommand}[1]{\expandafter\providecommand\csname #1\endcsname{}%
\expandafter\renewcommand\csname #1\endcsname}%
\newcommand{\newedenvironment}[1]{\newenvironment{#1}{}{}\renewenvironment{#1}}%
\let\newedcommand\renewedcommand
\let\renewedenvironment\newedenvironment
\makeatother
\let\mathon=$
\let\mathoff=$
\ifx\AtBeginDocument\undefined \newcommand{\AtBeginDocument}[1]{}\fi
\newbox\sizebox
\setlength{\hoffset}{0pt}\setlength{\voffset}{0pt}
\addtolength{\textheight}{\footskip}\setlength{\footskip}{0pt}
\addtolength{\textheight}{\topmargin}\setlength{\topmargin}{0pt}
\addtolength{\textheight}{\headheight}\setlength{\headheight}{0pt}
\addtolength{\textheight}{\headsep}\setlength{\headsep}{0pt}
\setlength{\textwidth}{349pt}
\newwrite\lthtmlwrite
\makeatletter
\let\realnormalsize=\normalsize
\global\topskip=2sp
\def\preveqno{}\let\real@float=\@float \let\realend@float=\end@float
\def\@float{\let\@savefreelist\@freelist\real@float}
\def\liih@math{\ifmmode$\else\bad@math\fi}
\def\end@float{\realend@float\global\let\@freelist\@savefreelist}
\let\real@dbflt=\@dbflt \let\end@dblfloat=\end@float
\let\@largefloatcheck=\relax
\let\if@boxedmulticols=\iftrue
\def\@dbflt{\let\@savefreelist\@freelist\real@dbflt}
\def\adjustnormalsize{\def\normalsize{\mathsurround=0pt \realnormalsize
\parindent=0pt\abovedisplayskip=0pt\belowdisplayskip=0pt}%
\def\phantompar{\csname par\endcsname}\normalsize}%
\def\lthtmltypeout#1{{\let\protect\string \immediate\write\lthtmlwrite{#1}}}%
\newcommand\lthtmlhboxmathA{\adjustnormalsize\setbox\sizebox=\hbox\bgroup\kern.05em }%
\newcommand\lthtmlhboxmathB{\adjustnormalsize\setbox\sizebox=\hbox to\hsize\bgroup\hfill }%
\newcommand\lthtmlvboxmathA{\adjustnormalsize\setbox\sizebox=\vbox\bgroup %
\let\ifinner=\iffalse \let\)\liih@math }%
\newcommand\lthtmlboxmathZ{\@next\next\@currlist{}{\def\next{\voidb@x}}%
\expandafter\box\next\egroup}%
\newcommand\lthtmlmathtype[1]{\gdef\lthtmlmathenv{#1}}%
\newcommand\lthtmllogmath{\lthtmltypeout{l2hSize %
:\lthtmlmathenv:\the\ht\sizebox::\the\dp\sizebox::\the\wd\sizebox.\preveqno}}%
\newcommand\lthtmlfigureA[1]{\let\@savefreelist\@freelist
\lthtmlmathtype{#1}\lthtmlvboxmathA}%
\newcommand\lthtmlpictureA{\bgroup\catcode`\_=8 \lthtmlpictureB}%
\newcommand\lthtmlpictureB[1]{\lthtmlmathtype{#1}\egroup
\let\@savefreelist\@freelist \lthtmlhboxmathB}%
\newcommand\lthtmlpictureZ[1]{\hfill\lthtmlfigureZ}%
\newcommand\lthtmlfigureZ{\lthtmlboxmathZ\lthtmllogmath\copy\sizebox
\global\let\@freelist\@savefreelist}%
\newcommand\lthtmldisplayA{\bgroup\catcode`\_=8 \lthtmldisplayAi}%
\newcommand\lthtmldisplayAi[1]{\lthtmlmathtype{#1}\egroup\lthtmlvboxmathA}%
\newcommand\lthtmldisplayB[1]{\edef\preveqno{(\theequation)}%
\lthtmldisplayA{#1}\let\@eqnnum\relax}%
\newcommand\lthtmldisplayZ{\lthtmlboxmathZ\lthtmllogmath\lthtmlsetmath}%
\newcommand\lthtmlinlinemathA{\bgroup\catcode`\_=8 \lthtmlinlinemathB}
\newcommand\lthtmlinlinemathB[1]{\lthtmlmathtype{#1}\egroup\lthtmlhboxmathA
\vrule height1.5ex width0pt }%
\newcommand\lthtmlinlineA{\bgroup\catcode`\_=8 \lthtmlinlineB}%
\newcommand\lthtmlinlineB[1]{\lthtmlmathtype{#1}\egroup\lthtmlhboxmathA}%
\newcommand\lthtmlinlineZ{\egroup\expandafter\ifdim\dp\sizebox>0pt %
\expandafter\centerinlinemath\fi\lthtmllogmath\lthtmlsetinline}
\newcommand\lthtmlinlinemathZ{\egroup\expandafter\ifdim\dp\sizebox>0pt %
\expandafter\centerinlinemath\fi\lthtmllogmath\lthtmlsetmath}
\newcommand\lthtmlindisplaymathZ{\egroup %
\centerinlinemath\lthtmllogmath\lthtmlsetmath}
\def\lthtmlsetinline{\hbox{\vrule width.1em \vtop{\vbox{%
\kern.1em\copy\sizebox}\ifdim\dp\sizebox>0pt\kern.1em\else\kern.3pt\fi
\ifdim\hsize>\wd\sizebox \hrule depth1pt\fi}}}
\def\lthtmlsetmath{\hbox{\vrule width.1em\kern-.05em\vtop{\vbox{%
\kern.1em\kern0.8 pt\hbox{\hglue.17em\copy\sizebox\hglue0.8 pt}}\kern.3pt%
\ifdim\dp\sizebox>0pt\kern.1em\fi \kern0.8 pt%
\ifdim\hsize>\wd\sizebox \hrule depth1pt\fi}}}
\def\centerinlinemath{%
\dimen1=\ifdim\ht\sizebox<\dp\sizebox \dp\sizebox\else\ht\sizebox\fi
\advance\dimen1by.5pt \vrule width0pt height\dimen1 depth\dimen1
\dp\sizebox=\dimen1\ht\sizebox=\dimen1\relax}
\def\lthtmlcheckvsize{\ifdim\ht\sizebox<\vsize
\ifdim\wd\sizebox<\hsize\expandafter\hfill\fi \expandafter\vfill
\else\expandafter\vss\fi}%
\providecommand{\selectlanguage}[1]{}%
\makeatletter \tracingstats = 1
\begin{document}
\pagestyle{empty}\thispagestyle{empty}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength hsize=\the\hsize}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength vsize=\the\vsize}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength hoffset=\the\hoffset}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength voffset=\the\voffset}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength topmargin=\the\topmargin}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength topskip=\the\topskip}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength headheight=\the\headheight}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength headsep=\the\headsep}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength parskip=\the\parskip}\lthtmltypeout{}%
\lthtmltypeout{latex2htmlLength oddsidemargin=\the\oddsidemargin}\lthtmltypeout{}%
\makeatletter
\if@twoside\lthtmltypeout{latex2htmlLength evensidemargin=\the\evensidemargin}%
\else\lthtmltypeout{latex2htmlLength evensidemargin=\the\oddsidemargin}\fi%
\lthtmltypeout{}%
\makeatother
\setcounter{page}{1}
\onecolumn
% !!! IMAGES START HERE !!!
\stepcounter{section}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{section}
\stepcounter{subsection}
\stepcounter{subsubsection}
\stepcounter{subsubsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsubsection}
\stepcounter{subsubsection}
\stepcounter{subsubsection}
\stepcounter{subsection}
\stepcounter{subsubsection}
\stepcounter{section}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsubsection}
\stepcounter{subsubsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{section}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{section}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\appendix
\stepcounter{section}
\stepcounter{section}
{\newpage\clearpage
\lthtmlinlinemathA{tex2html_wrap_inline807}%
$\copyright$%
\lthtmlinlinemathZ
\lthtmlcheckvsize\clearpage}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\stepcounter{subsection}
\end{document}
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" href="contents.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="ZODB/ZEO Programming Guide">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>ZODB/ZEO Programming Guide</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><A href="contents.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Next:</b> <a class="sectref" href="contents.html">Contents</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<div class="titlepage">
<center>
<h1>ZODB/ZEO Programming Guide</h1>
<p><b><font size="+2">A.M. Kuchling</font></b></p>
<p>akuchlin@mems-exchange.org</p>
<p><strong>Release 0.04</strong><br>
<strong>17 January 2003</strong></p>
<p>
</center>
</div>
<p><hr>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"></a>
<UL CLASS="ChildLinks">
<LI><A href="contents.html">Contents</a>
<LI><A href="node2.html">1 Introduction</a>
<UL>
<LI><A href="node3.html">1.1 What is the ZODB?</a>
<LI><A href="node4.html">1.2 OODBs vs. Relational DBs</a>
<LI><A href="node5.html">1.3 What is ZEO?</a>
<LI><A href="node6.html">1.4 About this guide</a>
<LI><A href="node7.html">1.5 Acknowledgements</a>
</ul>
<LI><A href="node8.html">2 ZODB Programming</a>
<UL>
<LI><A href="node9.html">2.1 Installing ZODB</a>
<UL>
<LI><A href="node10.html">2.1.1 Requirements</a>
<LI><A href="node11.html">2.1.2 Installing the Packages</a>
</ul>
<LI><A href="node12.html">2.2 How ZODB Works</a>
<LI><A href="node13.html">2.3 Opening a ZODB</a>
<LI><A href="node14.html">2.4 Writing a Persistent Class</a>
<LI><A href="node15.html">2.5 Rules for Writing Persistent Classes</a>
<UL>
<LI><A href="node16.html">2.5.1 Modifying Mutable Objects</a>
<LI><A href="node17.html">2.5.2 Some Special Methods Don't Work</a>
<LI><A href="node18.html">2.5.3 <tt class="method">__getattr__</tt>, <tt class="method">__delattr__</tt>, and <tt class="method">__setattr__</tt></a>
</ul>
<LI><A href="node19.html">2.6 Writing Persistent Classes</a>
<UL>
<LI><A href="node20.html">2.6.1 Changing Instance Attributes</a>
</ul>
</ul>
<LI><A href="zeo.html">3 ZEO</a>
<UL>
<LI><A href="node22.html">3.1 How ZEO Works</a>
<LI><A href="node23.html">3.2 Installing ZEO</a>
<UL>
<LI><A href="node24.html">3.2.1 Requirements</a>
<LI><A href="node25.html">3.2.2 Running a server</a>
</ul>
<LI><A href="node26.html">3.3 Testing the ZEO Installation</a>
<LI><A href="node27.html">3.4 ZEO Programming Notes</a>
<LI><A href="node28.html">3.5 Sample Application: chatter.py</a>
</ul>
<LI><A href="node29.html">4 Transactions and Versioning</a>
<UL>
<LI><A href="node30.html">4.1 Subtransactions</a>
<LI><A href="node31.html">4.2 Undoing Changes</a>
<LI><A href="node32.html">4.3 Versions</a>
<LI><A href="node33.html">4.4 Multithreaded ZODB Programs</a>
</ul>
<LI><A href="node34.html">5 Related Modules</a>
<UL>
<LI><A href="node35.html">5.1 <tt class="module">ZODB.PersistentMapping</tt></a>
<LI><A href="node36.html">5.2 <tt class="module">ZODB.PersistentList</tt></a>
<LI><A href="node37.html">5.3 BTrees Package</a>
</ul>
<LI><A href="node38.html">A. Resources</a>
<LI><A href="node39.html">B. GNU Free Documentation License</a>
<UL>
<LI><A href="node40.html">Preamble</a>
<LI><A href="node41.html">B..1 Applicability and Definitions</a>
<LI><A href="node42.html">B..2 Verbatim Copying</a>
<LI><A href="node43.html">B..3 Copying in Quantity</a>
<LI><A href="node44.html">B..4 Modifications</a>
<LI><A href="node45.html">B..5 Combining Documents</a>
<LI><A href="node46.html">B..6 Collections of Documents</a>
<LI><A href="node47.html">B..7 Aggregation With Independent Works</a>
<LI><A href="node48.html">B..8 Translation</a>
<LI><A href="node49.html">B..9 Termination</a>
<LI><A href="node50.html">B..10 Future Revisions of This Licence</a>
<LI><A href="node51.html">ADDENDUM: How to use this License for your documents</a>
</ul>
<LI><A href="about.html">About this document ...</a>
</ul>
<!--End of Table of Child-Links-->
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><A href="contents.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Next:</b> <a class="sectref" href="contents.html">Contents</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node11.html">
<LINK REL="previous" HREF="node9.html">
<LINK REL="up" HREF="node9.html">
<LINK REL="next" HREF="node11.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.1.1 Requirements">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.1.1 Requirements</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node9.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node9.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node11.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node9.html">2.1 Installing ZODB</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node9.html">2.1 Installing ZODB</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node11.html">2.1.2 Installing the Packages</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000311000000000000000">
2.1.1 Requirements</A>
</H3>
<P>
You will need Python 2.1 or higher. The code is packaged using
Distutils. So it is simply a matter of untarring or unzipping the
release package, and then running <code>python setup.py install</code>.
<P>
You'll need a C compiler to build the packages, because there are
various C extension modules. At the moment no one is making Windows
binaries available, so you'll need a Windows development environment
to build ZODB.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node9.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node9.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node11.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node9.html">2.1 Installing ZODB</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node9.html">2.1 Installing ZODB</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node11.html">2.1.2 Installing the Packages</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="previous" HREF="node10.html">
<LINK REL="up" HREF="node9.html">
<LINK REL="next" HREF="node12.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.1.2 Installing the Packages">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.1.2 Installing the Packages</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node10.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node9.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node12.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node10.html">2.1.1 Requirements</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node9.html">2.1 Installing ZODB</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node12.html">2.2 How ZODB Works</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000312000000000000000">
2.1.2 Installing the Packages</A>
</H3>
<P>
Download the ZODB tarball containing all the packages for both ZODB
and ZEO from <a class="url" href="http://www.zope.org/Products/StandaloneZODB">http://www.zope.org/Products/StandaloneZODB</a>. See
the <span class="file">README.txt</span> file in the top level of the release directory
for details on building, testing, and installing.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node10.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node9.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node12.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node10.html">2.1.1 Requirements</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node9.html">2.1 Installing ZODB</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node12.html">2.2 How ZODB Works</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node13.html">
<LINK REL="previous" HREF="node9.html">
<LINK REL="up" HREF="node8.html">
<LINK REL="next" HREF="node13.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.2 How ZODB Works">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.2 How ZODB Works</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node11.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node13.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node11.html">2.1.2 Installing the Packages</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node13.html">2.3 Opening a ZODB</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000320000000000000000">
2.2 How ZODB Works</A>
</H2>
<P>
The ZODB is conceptually simple. Python classes subclass a
<tt class="class">Persistent</tt> class to become ZODB-aware.
Instances of persistent objects are brought in from a permanent
storage medium, such as a disk file, when the program needs them, and
remain cached in RAM. The ZODB traps modifications to objects, so
that when a statement such as <code>obj.size = 1</code> is executed, the
modified object is marked as ``dirty''. On request, any dirty objects
are written out to permanent storage; this is called committing a
transaction. Transactions can also be aborted or rolled back, which
results in any changes being discarded, dirty objects reverting to
their initial state before the transaction began.
<P>
The term ``transaction'' has a specific technical meaning in computer
science. It's extremely important that the contents of a database
don't get corrupted by software or hardware crashes, and most database
software offers protection against such corruption by supporting four
useful properties, Atomicity, Consistency, Isolation, and Durability.
In computer science jargon these four terms are collectively dubbed
the ACID properties, forming an acronym from their names. The
definitions of the ACID properties are:
<P>
<DL COMPACT>
<DT>Atomicity</DT>
<DD>means that any changes to data made during a transaction
are all-or-nothing. Either all the changes are applied, or none of
them are. If a program makes a bunch of modifications and then
crashes, the database won't be partially modified, potentially leaving
the data in an inconsistent state; instead all the changes will be
forgotten. That's bad, but it's better than having a
partially-applied modification put the database into an inconsistent
state.
<P>
</DD>
<DT>Consistency</DT>
<DD>means that the data cannot be placed into a
logically invalid state; sanity checks can be written and enforced.
Usually this is done by defining a database schema, and requiring
the data always matches the schema. There are two typical
approaches to consistency. One is to enforce rules about the types
of objects and attribute; for example, enforce that the
<code>order_number</code> attribute is always an integer, and not a
string, tuple, or other object. Another is to guarantee consistency
across data structures; for example, that any object with an
<code>order_number</code> attribute must also appear in the
<code>orders_table</code> object. In general, atomicity and isolation make
it possible for applications to provide consistency.
<P>
</DD>
<DT>Isolation</DT>
<DD>means that two programs or threads running in two
different transactions cannot see each other's changes until they
commit their transactions.
<P>
</DD>
<DT>Durability</DT>
<DD>means that once a transaction has been committed,
a subsequent crash will not cause any data to be lost or corrupted.
<P>
</DD>
</DL>
<P>
The ZODB provides 3 of the ACID properties. Only Consistency is not
supported; the ZODB has no notion of a database schema, and therefore
has no way of enforcing consistency with a schema.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node11.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node13.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node11.html">2.1.2 Installing the Packages</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node13.html">2.3 Opening a ZODB</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node14.html">
<LINK REL="previous" HREF="node12.html">
<LINK REL="up" HREF="node8.html">
<LINK REL="next" HREF="node14.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.3 Opening a ZODB">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.3 Opening a ZODB</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node12.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node14.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node12.html">2.2 How ZODB Works</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node14.html">2.4 Writing a Persistent</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000330000000000000000">
2.3 Opening a ZODB</A>
</H2>
<P>
There are 3 main interfaces supplied by the ZODB:
<tt class="class">Storage</tt>, <tt class="class">DB</tt>, and <tt class="class">Connection</tt> classes. The
<tt class="class">DB</tt> and <tt class="class">Connection</tt> interfaces both have single
implementations, but there are several different classes that
implement the <tt class="class">Storage</tt> interface.
<P>
<UL>
<LI><tt class="class">Storage</tt> classes are the lowest layer, and handle
storing and retrieving objects from some form of long-term storage.
A few different types of Storage have been written, such as
<tt class="class">FileStorage</tt>, which uses regular disk files, and
<tt class="class">bsddb3Storage</tt>, which uses Sleepycat Software's BerkeleyDB
database. You could write a new Storage that stored objects in a
relational database or Metakit file, for example, if that would
better suit your application. Two example storages,
<tt class="class">DemoStorage</tt> and <tt class="class">MappingStorage</tt>, are available to use
as models if you want to write a new Storage.
<P>
</LI>
<LI>The <tt class="class">DB</tt> class sits on top of a storage, and mediates the
interaction between several connections. One <tt class="class">DB</tt> instance is
created per process.
<P>
</LI>
<LI>Finally, the <tt class="class">Connection</tt> class caches objects, and moves
them into and out of object storage. A multi-threaded program should
open a separate <tt class="class">Connection</tt> instance for each thread.
Different threads can then modify objects and commit their
modifications independently.
<P>
</LI>
</UL>
<P>
Preparing to use a ZODB requires 3 steps: you have to open the
<tt class="class">Storage</tt>, then create a <tt class="class">DB</tt> instance that uses the <tt class="class">Storage</tt>, and then get
a <tt class="class">Connection</tt> from the <tt class="class">DB instance</tt>. All this is only a few lines of
code:
<P>
<div class="verbatim"><pre>
from ZODB import FileStorage, DB
storage = FileStorage.FileStorage('/tmp/test-filestorage.fs')
db = DB(storage)
conn = db.open()
</pre></div>
<P>
Note that you can use a completely different data storage mechanism by
changing the first line that opens a <tt class="class">Storage</tt>; the above example uses a
<tt class="class">FileStorage</tt>. In section&nbsp;<A href="zeo.html#zeo">3</A>, ``How ZEO Works'',
you'll see how ZEO uses this flexibility to good effect.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node12.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node14.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node12.html">2.2 How ZODB Works</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node14.html">2.4 Writing a Persistent</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node15.html">
<LINK REL="previous" HREF="node13.html">
<LINK REL="up" HREF="node8.html">
<LINK REL="next" HREF="node15.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.4 Writing a Persistent Class">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.4 Writing a Persistent Class</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node13.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node15.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node13.html">2.3 Opening a ZODB</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000340000000000000000">
2.4 Writing a Persistent Class</A>
</H2>
<P>
Making a Python class persistent is quite simple; it simply needs to
subclass from the <tt class="class">Persistent</tt> class, as shown in this example:
<P>
<div class="verbatim"><pre>
import ZODB
from Persistence import Persistent
class User(Persistent):
pass
</pre></div>
<P>
The apparently unnecessary <code>import ZODB</code> statement is
needed for the following <code>from...import</code> statement to work
correctly, since the ZODB code does some magical tricks with
importing.
<P>
The <tt class="class">Persistent</tt> base class is an <tt class="module">ExtensionClass</tt>
class. As a result, it not compatible with new-style classes or types
in Python 2.2 and up.
<P>
For simplicity, in the examples the <tt class="class">User</tt> class will
simply be used as a holder for a bunch of attributes. Normally the
class would define various methods that add functionality, but that
has no impact on the ZODB's treatment of the class.
<P>
The ZODB uses persistence by reachability; starting from a set of root
objects, all the attributes of those objects are made persistent,
whether they're simple Python data types or class instances. There's
no method to explicitly store objects in a ZODB database; simply
assign them as an attribute of an object, or store them in a mapping,
that's already in the database. This chain of containment must
eventually reach back to the root object of the database.
<P>
As an example, we'll create a simple database of users that allows
retrieving a <tt class="class">User</tt> object given the user's ID. First, we
retrieve the primary root object of the ZODB using the <tt class="method">root()</tt>
method of the <tt class="class">Connection</tt> instance. The root object behaves
like a Python dictionary, so you can just add a new key/value pair for
your application's root object. We'll insert a <tt class="class">BTree</tt> object
that will contain all the <tt class="class">User</tt> objects. (The
<tt class="class">BTree</tt> module is also included as part of Zope.)
<P>
<div class="verbatim"><pre>
dbroot = conn.root()
# Ensure that a 'userdb' key is present
# in the root
if not dbroot.has_key('userdb'):
import BTree
dbroot['userdb'] = BTree.BTree()
userdb = dbroot['userdb']
</pre></div>
<P>
Inserting a new user is simple: create the <tt class="class">User</tt> object, fill
it with data, insert it into the <tt class="class">BTree</tt> instance, and commit
this transaction.
<P>
<div class="verbatim"><pre># Create new User instance
newuser = User()
# Add whatever attributes you want to track
newuser.id = 'amk'
newuser.first_name = 'Andrew' ; newuser.last_name = 'Kuchling'
...
# Add object to the BTree, keyed on the ID
userdb[newuser.id] = newuser
# Commit the change
get_transaction().commit()
</pre></div>
<P>
When you import the ZODB package, it adds a new function,
<tt class="function">get_transaction()</tt>, to Python's collection of built-in
functions. <tt class="function">get_transaction()</tt> returns a <tt class="class">Transaction</tt>
object, which has two important methods: <tt class="method">commit()</tt> and
<tt class="method">abort()</tt>. <tt class="method">commit()</tt> writes any modified objects
to disk, making the changes permanent, while <tt class="method">abort()</tt> rolls
back any changes that have been made, restoring the original state of
the objects. If you're familiar with database transactional
semantics, this is all what you'd expect.
<P>
Because the integration with Python is so complete, it's a lot like
having transactional semantics for your program's variables, and you
can experiment with transactions at the Python interpreter's prompt:
<P>
<div class="verbatim"><pre>&gt;&gt;&gt; newuser
&lt;User instance at 81b1f40&gt;
&gt;&gt;&gt; newuser.first_name # Print initial value
'Andrew'
&gt;&gt;&gt; newuser.first_name = 'Bob' # Change first name
&gt;&gt;&gt; newuser.first_name # Verify the change
'Bob'
&gt;&gt;&gt; get_transaction().abort() # Abort transaction
&gt;&gt;&gt; newuser.first_name # The value has changed back
'Andrew'
</pre></div>
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node13.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node15.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node13.html">2.3 Opening a ZODB</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node19.html">
<LINK REL="previous" HREF="node14.html">
<LINK REL="up" HREF="node8.html">
<LINK REL="next" HREF="node16.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.5 Rules for Writing Persistent Classes">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.5 Rules for Writing Persistent Classes</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node14.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node16.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node14.html">2.4 Writing a Persistent</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node16.html">2.5.1 Modifying Mutable Objects</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000350000000000000000">
2.5 Rules for Writing Persistent Classes</A>
</H2>
<P>
Practically all persistent languages impose some restrictions on
programming style, warning against constructs they can't handle or
adding subtle semantic changes, and the ZODB is no exception.
Happily, the ZODB's restrictions are fairly simple to understand, and
in practice it isn't too painful to work around them.
<P>
The summary of rules is as follows:
<P>
<UL>
<LI>If you modify a mutable object that's the value of an object's
attribute, the ZODB can't catch that, and won't mark the object as
dirty.
The solution is to either set the dirty bit yourself when you modify
mutable objects, or use a wrapper for Python's lists and dictionaries
(<tt class="class">PersistentList</tt>,
<tt class="class">PersistentMapping</tt>)
that will set the dirty bit properly.
<P>
</LI>
<LI>Certain of Python's special methods don't work when they're
defined on ExtensionClasses. The most important ones are the
<tt class="method">__cmp__</tt> method, and the reversed versions of binary
arithmetic operations: <tt class="method">__radd__</tt>, <tt class="method">__rsub__</tt>, and so
forth.
<P>
</LI>
<LI>Recent versions of the ZODB allow writing a class with
<tt class="method">__setattr__</tt> , <tt class="method">__getattr__</tt>, or <tt class="method">__delattr__</tt> methods. (Older versions didn't support this at all.)
If you write such a <tt class="method">__setattr__</tt> or <tt class="method">__delattr__</tt> method,
its code has to set the dirty bit manually,
<P>
</LI>
</UL>
<P>
Let's look at each of these rules in detail.
<P>
<p><hr>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></a>
<UL CLASS="ChildLinks">
<LI><A href="node16.html">2.5.1 Modifying Mutable Objects</a>
<LI><A href="node17.html">2.5.2 Some Special Methods Don't Work</a>
<LI><A href="node18.html">2.5.3 <tt class="method">__getattr__</tt>, <tt class="method">__delattr__</tt>, and <tt class="method">__setattr__</tt></a>
</ul>
<!--End of Table of Child-Links-->
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node14.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node16.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node14.html">2.4 Writing a Persistent</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node16.html">2.5.1 Modifying Mutable Objects</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node17.html">
<LINK REL="previous" HREF="node15.html">
<LINK REL="up" HREF="node15.html">
<LINK REL="next" HREF="node17.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.5.1 Modifying Mutable Objects">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.5.1 Modifying Mutable Objects</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node15.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node15.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node17.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node17.html">2.5.2 Some Special Methods</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000351000000000000000">
2.5.1 Modifying Mutable Objects</A>
</H3>
<P>
The ZODB uses various Python hooks to catch attribute accesses, and
can trap most of the ways of modifying an object, but not all of them.
If you modify a <tt class="class">User</tt> object by assigning to one of its
attributes, as in <code>userobj.first_name = 'Andrew'</code>, the ZODB will
mark the object as having been changed, and it'll be written out on
the following <tt class="method">commit()</tt>.
<P>
The most common idiom that <i>isn't</i> caught by the ZODB is
mutating a list or dictionary. If <tt class="class">User</tt> objects have a
attribute named <code>friends</code> containing a list, calling
<code>userobj.friends.append(otherUser)</code> doesn't mark
<code>userobj</code> as modified; from the ZODB's point of
view, <code>userobj.friends</code> was only read, and its value, which
happened to be an ordinary Python list, was returned. The ZODB isn't
aware that the object returned was subsequently modified.
<P>
This is one of the few quirks you'll have to remember when using the
ZODB; if you modify a mutable attribute of an object in place, you
have to manually mark the object as having been modified by setting
its dirty bit to true. This is done by setting the
<tt class="member">_p_changed</tt> attribute of the object to true:
<P>
<div class="verbatim"><pre>
userobj.friends.append(otherUser)
userobj._p_changed = 1
</pre></div>
<P>
An obsolete way of doing this that's still supported is calling the
<tt class="method">__changed__()</tt> method instead, but setting <tt class="member">_p_changed</tt>
is the preferred way.
<P>
You can hide the implementation detail of having to mark objects as
dirty by designing your class's API to not use direct attribute
access; instead, you can use the Java-style approach of accessor
methods for everything, and then set the dirty bit within the accessor
method. For example, you might forbid accessing the <code>friends</code>
attribute directly, and add a <tt class="method">get_friend_list()</tt> accessor and
an <tt class="method">add_friend()</tt> modifier method to the class. <tt class="method">add_friend()</tt>
would then look like this:
<P>
<div class="verbatim"><pre>
def add_friend(self, friend):
self.friends.append(otherUser)
self._p_changed = 1
</pre></div>
<P>
Alternatively, you could use a ZODB-aware list or mapping type that
handles the dirty bit for you. The ZODB comes with a
<tt class="class">PersistentMapping</tt> class, and I've contributed a
<tt class="class">PersistentList</tt> class that's included in my ZODB distribution,
and may make it into a future upstream release of Zope.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node15.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node15.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node17.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node17.html">2.5.2 Some Special Methods</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node18.html">
<LINK REL="previous" HREF="node16.html">
<LINK REL="up" HREF="node15.html">
<LINK REL="next" HREF="node18.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.5.2 Some Special Methods Don't Work">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.5.2 Some Special Methods Don't Work</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node16.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node15.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node18.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node16.html">2.5.1 Modifying Mutable Objects</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node18.html">2.5.3 __getattr__, __delattr__, and</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000352000000000000000">
2.5.2 Some Special Methods Don't Work</A>
</H3>
<P>
Don't bother defining certain special methods on
ExtensionClasses, because they won't work. Most notably, the
<tt class="method">__cmp__</tt> method on an ExtensionClass will never be called.
Neither will the reversed versions of binary arithmetic operations,
such as <tt class="method">__radd__</tt> and <tt class="method">__rsub__</tt>.
<P>
This is a moderately annoying limitation. It means that the
<tt class="class">PersistentList</tt> class can't implement comparisons with regular
sequence objects, and therefore statements such as
<code>if perslist==[]</code> don't do what you expect; instead of performing the correct
comparison, they return some arbitrary fixed result, so the <code>if</code>
statement will always be true or always be false. There is no good
solution to this problem at the moment, so all you can do is design
class interfaces that don't need to overload
<tt class="method">__cmp__</tt> or the <tt class="method">__r*__</tt> methods.
<P>
This limitation is mostly Python's fault. As of Python 2.1, the most
recent version at this writing, the code which handles comparing two
Python objects contains a hard-wired check for objects that are class
instances, which means that <code>type(obj) == types.InstanceType</code>.
The code inside the Python interpreter looks like this:
<P>
<div class="verbatim"><pre>
/* Code to compare objects v and w */
if (PyInstance_Check(v) || PyInstance_Check(w))
return PyInstance_DoBinOp(v, w, "__cmp__", "__rcmp__", do_cmp);
/* Do usual Python comparison of v,w */
c = PyObject_Compare(v, w);
</pre></div>
<P>
While ExtensionClasses try to behave as much like regular Python
instances as possible, they are still not instances, and
<tt class="function">type()</tt> doesn't return the <code>InstanceType</code> object, so
no attempt is ever made to call <tt class="method">__cmp__</tt>. Perhaps Python 2.2
will repair this.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node16.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node15.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node18.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node16.html">2.5.1 Modifying Mutable Objects</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node18.html">2.5.3 __getattr__, __delattr__, and</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="previous" HREF="node17.html">
<LINK REL="up" HREF="node15.html">
<LINK REL="next" HREF="node19.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.5.3 __getattr__, __delattr__, and __setattr__">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.5.3 __getattr__, __delattr__, and __setattr__</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node17.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node15.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node19.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node17.html">2.5.2 Some Special Methods</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node19.html">2.6 Writing Persistent Classes</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000353000000000000000">
2.5.3 <tt class="method">__getattr__</tt>, <tt class="method">__delattr__</tt>, and <tt class="method">__setattr__</tt></A>
</H3>
<P>
Recent versions of ZODB allow writing persistent classes that have
<tt class="method">__getattr__</tt>, <tt class="method">__delattr__</tt>, or <tt class="method">__setattr__</tt>
methods. The one minor complication is that the machinery for
automatically detecting changes to the object is disabled while the
<tt class="method">__getattr__</tt>, <tt class="method">__delattr__</tt>, or <tt class="method">__setattr__</tt>
method is executing. This means that if the object is modified, the
object should be marked as dirty by setting the object's
<tt class="member">_p_changed</tt> method to true.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node17.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node15.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node19.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node17.html">2.5.2 Some Special Methods</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node15.html">2.5 Rules for Writing</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node19.html">2.6 Writing Persistent Classes</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="previous" HREF="node15.html">
<LINK REL="up" HREF="node8.html">
<LINK REL="next" HREF="node20.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.6 Writing Persistent Classes">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.6 Writing Persistent Classes</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node18.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node20.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node18.html">2.5.3 __getattr__, __delattr__, and</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node20.html">2.6.1 Changing Instance Attributes</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000360000000000000000">
2.6 Writing Persistent Classes</A>
</H2>
<P>
Now that we've looked at the basics of programming using the ZODB,
we'll turn to some more subtle tasks that are likely to come up for
anyone using the ZODB in a production system.
<P>
<p><hr>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></a>
<UL CLASS="ChildLinks">
<LI><A href="node20.html">2.6.1 Changing Instance Attributes</a>
</ul>
<!--End of Table of Child-Links-->
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node18.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node8.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node20.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node18.html">2.5.3 __getattr__, __delattr__, and</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node8.html">2 ZODB Programming</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node20.html">2.6.1 Changing Instance Attributes</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node8.html">
<LINK REL="previous" href="contents.html">
<LINK REL="up" HREF="zodb.html">
<LINK REL="next" HREF="node3.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="1 Introduction">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>1 Introduction</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A href="contents.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node3.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" href="contents.html">Contents</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node3.html">1.1 What is the</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H1><A NAME="SECTION000200000000000000000">
1 Introduction</A>
</H1>
<P>
This guide explains how to write Python programs that use the Z Object
Database (ZODB) and Zope Enterprise Objects (ZEO). The latest version
of the guide is always available at
<a class="url" href="http://www.amk.ca/zodb/guide/">http://www.amk.ca/zodb/guide/</a>.
<P>
<p><hr>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></a>
<UL CLASS="ChildLinks">
<LI><A href="node3.html">1.1 What is the ZODB?</a>
<LI><A href="node4.html">1.2 OODBs vs. Relational DBs</a>
<LI><A href="node5.html">1.3 What is ZEO?</a>
<LI><A href="node6.html">1.4 About this guide</a>
<LI><A href="node7.html">1.5 Acknowledgements</a>
</ul>
<!--End of Table of Child-Links-->
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A href="contents.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node3.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" href="contents.html">Contents</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node3.html">1.1 What is the</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="previous" HREF="node19.html">
<LINK REL="up" HREF="node19.html">
<LINK REL="next" href="zeo.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="2.6.1 Changing Instance Attributes">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>2.6.1 Changing Instance Attributes</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node19.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node19.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node19.html">2.6 Writing Persistent Classes</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node19.html">2.6 Writing Persistent Classes</A>
<b class="navlabel">Next:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000361000000000000000">
2.6.1 Changing Instance Attributes</A>
</H3>
<P>
Ideally, before making a class persistent you would get its interface
right the first time, so that no attributes would ever need to be
added, removed, or have their interpretation change over time. It's a
worthy goal, but also an impractical one unless you're gifted with
perfect knowledge of the future. Such unnatural foresight can't be
required of any person, so you therefore have to be prepared to handle
such structural changes gracefully. In object-oriented database
terminology, this is a schema update. The ZODB doesn't have an actual
schema specification, but you're changing the software's expectations
of the data contained by an object, so you're implicitly changing the
schema.
<P>
One way to handle such a change is to write a one-time conversion
program that will loop over every single object in the database and
update them to match the new schema. This can be easy if your network
of object references is quite structured, making it easy to find all
the instances of the class being modified. For example, if all
<tt class="class">User</tt> objects can be found inside a single dictionary or
BTree, then it would be a simple matter to loop over every
<tt class="class">User</tt> instance with a <tt class="keyword">for</tt> statement.
This is more difficult if your object graph is less structured; if
<tt class="class">User</tt> objects can be found as attributes of any number of
different class instances, then there's no longer any easy way to find
them all, short of writing a generalized object traversal function
that would walk over every single object in a ZODB, checking each one
to see if it's an instance of <tt class="class">User</tt>.
<A NAME="tex2html1"
HREF="#foot262"><SUP>1</SUP></A>Some OODBs support a feature called extents, which allow quickly
finding all the instances of a given class, no matter where they are
in the object graph; unfortunately the ZODB doesn't offer extents as a
feature.
<P>
XXX Rest of section not written yet: __getstate__/__setstate__
<P>
<BR><HR><H4>Footnotes</H4>
<DL>
<DT><A NAME="foot262">...User.
</A><A
HREF="node20.html#tex2html1"><SUP>1</SUP></A></DT>
<DD>XXX is there a convenience method for walking the object graph hiding
somewhere inside DC's code? Should there be a utility method for
doing this? Should I write one and include it in this section?
</DD>
</DL>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node19.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node19.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node19.html">2.6 Writing Persistent Classes</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node19.html">2.6 Writing Persistent Classes</A>
<b class="navlabel">Next:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>2.6.1 Changing Instance Attributes</title>
<META NAME="description" CONTENT="2.6.1 Changing Instance Attributes">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<meta http-equiv="Content-Type" content="text/html; charset=">
<link rel="STYLESHEET" href="zodb.css">
<link rel="first" href="zodb.html">
<link rel="contents" href="contents.html" title="Contents">
<LINK REL="previous" HREF="node20.html">
<LINK REL="up" HREF="node20.html">
<LINK REL="next" href="zeo.html">
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node20.html"><img src="/python/writing/icons/previous.gif"
border="0" height="32"
alt="Previous Page" width="32"></A></td>
<td><A HREF="node20.html"><img src="/python/writing/icons/up.gif"
border="0" height="32"
alt="Up One Level" width="32"></A></td>
<td><A href="zeo.html"><img src="/python/writing/icons/next.gif"
border="0" height="32"
alt="Next Page" width="32"></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src="/python/writing/icons/contents.gif"
border="0" height="32"
alt="Contents" width="32"></A></td>
<td><img src="/python/writing/icons/blank.gif"
border="0" height="32"
alt="" width="32"></td>
<td><img src="/python/writing/icons/blank.gif"
border="0" height="32"
alt="" width="32"></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node20.html">2.6 Writing Persistent Classes</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node20.html">2.6 Writing Persistent Classes</A>
<b class="navlabel">Next:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000361000000000000000">
2.6.1 Changing Instance Attributes</A>
</H3>
<P>
Ideally, before making a class persistent you would get its interface
right the first time, so that no attributes would ever need to be
added, removed, or have their interpretation change over time. It's a
worthy goal, but also an impractical one unless you're gifted with
perfect knowledge of the future. Such unnatural foresight can't be
required of any person, so you therefore have to be prepared to handle
such structural changes gracefully. In object-oriented database
terminology, this is a schema update. The ZODB doesn't have an actual
schema specification, but you're changing the software's expectations
of the data contained by an object, so you're implicitly changing the
schema.
<P>
One way to handle such a change is to write a one-time conversion
program that will loop over every single object in the database and
update them to match the new schema. This can be easy if your network
of object references is quite structured, making it easy to find all
the instances of the class being modified. For example, if all
<tt class="class">User</tt> objects can be found inside a single dictionary or
B-tree, then it would be a simple matter to loop over every
<tt class="class">User</tt> instance with a <tt class="keyword">for</tt> statement.
This is more difficult if your object graph is less structured; if
<tt class="class">User</tt> objects can be found as attributes of any number of
different class instances, then there's no longer any easy way to find
them all, short of writing a generalized object traversal function
that would walk over every single object in a ZODB, checking each one
to see if it's an instance of <tt class="class">User</tt>.
<A NAME="tex2html1"
HREF="#foot287"><SUP>1</SUP></A>Some OODBs support a feature called extents, which allow quickly
finding all the instances of a given class, no matter where they are
in the object graph; unfortunately the ZODB doesn't offer extents as a
feature.
<P>
XXX Rest of section not written yet: __getstate__/__setstate__
<P>
<BR><HR><H4>Footnotes</H4>
<DL>
<DT><A NAME="foot287">...User.
</A><A NAME="foot287"
HREF="node21.html#tex2html1"><SUP>1</SUP></A>
<DD>XXX is there a convenience method for walking the object graph hiding
somewhere inside DC's code? Should there be a utility method for
doing this? Should I write one and include it in this section?
</DL>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node20.html"><img src="/python/writing/icons/previous.gif"
border="0" height="32"
alt="Previous Page" width="32"></A></td>
<td><A HREF="node20.html"><img src="/python/writing/icons/up.gif"
border="0" height="32"
alt="Up One Level" width="32"></A></td>
<td><A href="zeo.html"><img src="/python/writing/icons/next.gif"
border="0" height="32"
alt="Next Page" width="32"></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src="/python/writing/icons/contents.gif"
border="0" height="32"
alt="Contents" width="32"></A></td>
<td><img src="/python/writing/icons/blank.gif"
border="0" height="32"
alt="" width="32"></td>
<td><img src="/python/writing/icons/blank.gif"
border="0" height="32"
alt="" width="32"></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node20.html">2.6 Writing Persistent Classes</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node20.html">2.6 Writing Persistent Classes</A>
<b class="navlabel">Next:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<hr>
<span class="release-info">Release 0.03, documentation updated on February 8, 2002.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node23.html">
<LINK REL="previous" href="zeo.html">
<LINK REL="up" href="zeo.html">
<LINK REL="next" HREF="node23.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="3.1 How ZEO Works">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>3.1 How ZEO Works</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A href="zeo.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node23.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node23.html">3.2 Installing ZEO</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000410000000000000000">
3.1 How ZEO Works</A>
</H2>
<P>
The ZODB, as I've described it so far, can only be used within a
single Python process (though perhaps with multiple threads). ZEO,
Zope Enterprise Objects, extends the ZODB machinery to provide access
to objects over a network. The name "Zope Enterprise Objects" is a
bit misleading; ZEO can be used to store Python objects and access
them in a distributed fashion without Zope ever entering the picture.
The combination of ZEO and ZODB is essentially a Python-specific
object database.
<P>
ZEO consists of about 6000 lines of Python code, excluding tests. The
code is relatively small because it contains only code for a TCP/IP
server, and for a new type of Storage, <tt class="class">ClientStorage</tt>.
<tt class="class">ClientStorage</tt> simply makes remote procedure calls to the
server, which then passes them on a regular <tt class="class">Storage</tt> class such
as <tt class="class">FileStorage</tt>. The following diagram lays out the system:
<P>
XXX insert diagram here later
<P>
Any number of processes can create a <tt class="class">ClientStorage</tt>
instance, and any number of threads in each process can be using that
instance. <tt class="class">ClientStorage</tt> aggressively caches objects
locally, so in order to avoid using stale data. The ZEO server sends
an invalidation message to all the connected <tt class="class">ClientStorage</tt>
instances on every write operation. The invalidation message contains
the object ID for each object that's been modified, letting the
<tt class="class">ClientStorage</tt> instances delete the old data for the
given object from their caches.
<P>
This design decision has some consequences you should be aware of.
First, while ZEO isn't tied to Zope, it was first written for use with
Zope, which stores HTML, images, and program code in the database. As
a result, reads from the database are <i>far</i> more frequent than
writes, and ZEO is therefore better suited for read-intensive
applications. If every <tt class="class">ClientStorage</tt> is writing to the
database all the time, this will result in a storm of invalidate
messages being sent, and this might take up more processing time than
the actual database operations themselves.<A NAME="tex2html2"
HREF="#foot429"><SUP>2</SUP></A>
<P>
On the other hand, for applications that have few writes in comparison
to the number of read accesses, this aggressive caching can be a major
win. Consider a Slashdot-like discussion forum that divides the load
among several Web servers. If news items and postings are represented
by objects and accessed through ZEO, then the most heavily accessed
objects - the most recent or most popular postings - will very
quickly wind up in the caches of the
<tt class="class">ClientStorage</tt> instances on the front-end servers. The
back-end ZEO server will do relatively little work, only being called
upon to return the occasional older posting that's requested, and to
send the occasional invalidate message when a new posting is added.
The ZEO server isn't going to be contacted for every single request,
so its workload will remain manageable.
<P>
<BR><HR><H4>Footnotes</H4>
<DL>
<DT><A NAME="foot429">... themselves.</A><A
HREF="node22.html#tex2html2"><SUP>2</SUP></A></DT>
<DD>These messages are
small and sent in batches, so there would need to be a lot of writes
before it became a problem.
</DD>
</DL>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A href="zeo.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node23.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node23.html">3.2 Installing ZEO</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node26.html">
<LINK REL="previous" HREF="node22.html">
<LINK REL="up" href="zeo.html">
<LINK REL="next" HREF="node24.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="3.2 Installing ZEO">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>3.2 Installing ZEO</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node22.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node24.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node22.html">3.1 How ZEO Works</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node24.html">3.2.1 Requirements</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000420000000000000000">
3.2 Installing ZEO</A>
</H2>
<P>
This section covers how to install the ZEO package, and how to
configure and run a ZEO Storage Server on a machine.
<P>
<p><hr>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></a>
<UL CLASS="ChildLinks">
<LI><A href="node24.html">3.2.1 Requirements</a>
<LI><A href="node25.html">3.2.2 Running a server</a>
</ul>
<!--End of Table of Child-Links-->
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node22.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node24.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node22.html">3.1 How ZEO Works</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node24.html">3.2.1 Requirements</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node25.html">
<LINK REL="previous" HREF="node23.html">
<LINK REL="up" HREF="node23.html">
<LINK REL="next" HREF="node25.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="3.2.1 Requirements">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>3.2.1 Requirements</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node23.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node23.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node25.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node23.html">3.2 Installing ZEO</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node23.html">3.2 Installing ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node25.html">3.2.2 Running a server</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000421000000000000000">
3.2.1 Requirements</A>
</H3>
<P>
The ZEO server software is included in ZODB3. As with the rest of
ZODB3, you'll need Python 2.1 or higher.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node23.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node23.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node25.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node23.html">3.2 Installing ZEO</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node23.html">3.2 Installing ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node25.html">3.2.2 Running a server</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="previous" HREF="node24.html">
<LINK REL="up" HREF="node23.html">
<LINK REL="next" HREF="node26.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="3.2.2 Running a server">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>3.2.2 Running a server</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node24.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node23.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node26.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node24.html">3.2.1 Requirements</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node23.html">3.2 Installing ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node26.html">3.3 Testing the ZEO</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H3><A NAME="SECTION000422000000000000000">
3.2.2 Running a server</A>
</H3>
<P>
The start.py script in the ZEO directory can be used to start a
server. Run it with the -h option to see the various values. If
you're just experimenting, a good choise is to use
<code>python ZEO/start.py -D -U /tmp/zeosocket</code> to run ZEO in
debug mode and with a Unix domain socket.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node24.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node23.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node26.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node24.html">3.2.1 Requirements</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node23.html">3.2 Installing ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node26.html">3.3 Testing the ZEO</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node27.html">
<LINK REL="previous" HREF="node23.html">
<LINK REL="up" href="zeo.html">
<LINK REL="next" HREF="node27.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="3.3 Testing the ZEO Installation">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>3.3 Testing the ZEO Installation</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node25.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node27.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node25.html">3.2.2 Running a server</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node27.html">3.4 ZEO Programming Notes</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000430000000000000000">
3.3 Testing the ZEO Installation</A>
</H2>
<P>
Once a ZEO server is up and running, using it is just like using ZODB
with a more conventional disk-based storage; no new programming
details are introduced by using a remote server. The only difference
is that programs must create a <tt class="class">ClientStorage</tt> instance instead
of a <tt class="class">FileStorage</tt> instance. From that point onward, ZODB-based
code is happily unaware that objects are being retrieved from a ZEO
server, and not from the local disk.
<P>
As an example, and to test whether ZEO is working correctly, try
running the following lines of code, which will connect to the server,
add some bits of data to the root of the ZODB, and commits the
transaction:
<P>
<div class="verbatim"><pre>
from ZEO import ClientStorage
from ZODB import DB
# Change next line to connect to your ZEO server
addr = ('kronos.example.com', 1975)
storage = ClientStorage.ClientStorage(addr)
db = DB(storage)
conn = db.open()
root = conn.root()
# Store some things in the root
root['list'] = ['a', 'b', 1.0, 3]
root['dict'] = {'a':1, 'b':4}
# Commit the transaction
get_transaction().commit()
</pre></div>
<P>
If this code runs properly, then your ZEO server is working correctly.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node25.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node27.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node25.html">3.2.2 Running a server</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node27.html">3.4 ZEO Programming Notes</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node28.html">
<LINK REL="previous" HREF="node26.html">
<LINK REL="up" href="zeo.html">
<LINK REL="next" HREF="node28.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="3.4 ZEO Programming Notes">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>3.4 ZEO Programming Notes</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node26.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node28.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node26.html">3.3 Testing the ZEO</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node28.html">3.5 Sample Application: chatter.py</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000440000000000000000">
3.4 ZEO Programming Notes</A>
</H2>
<P>
ZEO is written using <tt class="module">asyncore</tt>, from the Python standard
library. It assumes that some part of the user application is running
an <tt class="module">asyncore</tt> mainloop. For example, Zope run the loop in a
separate thread and ZEO uses that. If your application does not have
a mainloop, ZEO will not process incoming invalidation messages until
you make some call into ZEO. The <tt class="method">Connection.sync</tt> method can
be used to process pending invalidation messages. You can call it
when you want to make sure the <tt class="class">Connection</tt> has the most recent
version of every object, but you don't have any other work for ZEO to do.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node26.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node28.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node26.html">3.3 Testing the ZEO</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node28.html">3.5 Sample Application: chatter.py</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="previous" HREF="node27.html">
<LINK REL="up" href="zeo.html">
<LINK REL="next" HREF="node29.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="3.5 Sample Application: chatter.py">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>3.5 Sample Application: chatter.py</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node27.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node27.html">3.4 ZEO Programming Notes</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000450000000000000000">
3.5 Sample Application: chatter.py</A>
</H2>
<P>
For an example application, we'll build a little chat application.
What's interesting is that none of the application's code deals with
network programming at all; instead, an object will hold chat
messages, and be magically shared between all the clients through ZEO.
I won't present the complete script here; it's included in my ZODB
distribution, and you can download it from
<a class="url" href="http://www.amk.ca/zodb/demos/">http://www.amk.ca/zodb/demos/</a>. Only the interesting portions of
the code will be covered here.
<P>
The basic data structure is the <tt class="class">ChatSession</tt> object,
which provides an <tt class="method">add_message()</tt> method that adds a
message, and a <tt class="method">new_messages()</tt> method that returns a list
of new messages that have accumulated since the last call to
<tt class="method">new_messages()</tt>. Internally, <tt class="class">ChatSession</tt>
maintains a B-tree that uses the time as the key, and stores the
message as the corresponding value.
<P>
The constructor for <tt class="class">ChatSession</tt> is pretty simple; it simply
creates an attribute containing a B-tree:
<P>
<div class="verbatim"><pre>
class ChatSession(Persistent):
def __init__(self, name):
self.name = name
# Internal attribute: _messages holds all the chat messages.
self._messages = BTrees.OOBTree.OOBTree()
</pre></div>
<P>
<tt class="method">add_message()</tt> has to add a message to the
<code>_messages</code> B-tree. A complication is that it's possible
that some other client is trying to add a message at the same time;
when this happens, the client that commits first wins, and the second
client will get a <tt class="exception">ConflictError</tt> exception when it tries to
commit. For this application, <tt class="exception">ConflictError</tt> isn't serious
but simply means that the operation has to be retried; other
applications might treat it as a fatal error. The code uses
<code>try...except...else</code> inside a <code>while</code> loop,
breaking out of the loop when the commit works without raising an
exception.
<P>
<div class="verbatim"><pre>
def add_message(self, message):
"""Add a message to the channel.
message -- text of the message to be added
"""
while 1:
try:
now = time.time()
self._messages[now] = message
get_transaction().commit()
except ConflictError:
# Conflict occurred; this process should pause and
# wait for a little bit, then try again.
time.sleep(.2)
pass
else:
# No ConflictError exception raised, so break
# out of the enclosing while loop.
break
# end while
</pre></div>
<P>
<tt class="method">new_messages()</tt> introduces the use of <i>volatile</i>
attributes. Attributes of a persistent object that begin with
<code>_v_</code> are considered volatile and are never stored in the
database. <tt class="method">new_messages()</tt> needs to store the last time
the method was called, but if the time was stored as a regular
attribute, its value would be committed to the database and shared
with all the other clients. <tt class="method">new_messages()</tt> would then
return the new messages accumulated since any other client called
<tt class="method">new_messages()</tt>, which isn't what we want.
<P>
<div class="verbatim"><pre>
def new_messages(self):
"Return new messages."
# self._v_last_time is the time of the most recent message
# returned to the user of this class.
if not hasattr(self, '_v_last_time'):
self._v_last_time = 0
new = []
T = self._v_last_time
for T2, message in self._messages.items():
if T2 &gt; T:
new.append(message)
self._v_last_time = T2
return new
</pre></div>
<P>
This application is interesting because it uses ZEO to easily share a
data structure; ZEO and ZODB are being used for their networking
ability, not primarily for their data storage ability. I can foresee
many interesting applications using ZEO in this way:
<P>
<UL>
<LI>With a Tkinter front-end, and a cleverer, more scalable data
structure, you could build a shared whiteboard using the same
technique.
<P>
</LI>
<LI>A shared chessboard object would make writing a networked chess
game easy.
<P>
</LI>
<LI>You could create a Python class containing a CD's title and
track information. To make a CD database, a read-only ZEO server
could be opened to the world, or an HTTP or XML-RPC interface could
be written on top of the ZODB.
<P>
</LI>
<LI>A program like Quicken could use a ZODB on the local disk to
store its data. This avoids the need to write and maintain
specialized I/O code that reads in your objects and writes them out;
instead you can concentrate on the problem domain, writing objects
that represent cheques, stock portfolios, or whatever.
<P>
</LI>
</UL>
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node27.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A href="zeo.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node27.html">3.4 ZEO Programming Notes</A>
<b class="navlabel">Up:</b> <a class="sectref" href="zeo.html">3 ZEO</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node34.html">
<LINK REL="previous" href="zeo.html">
<LINK REL="up" HREF="zodb.html">
<LINK REL="next" HREF="node30.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="4 Transactions and Versioning">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>4 Transactions and Versioning</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node28.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node30.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node28.html">3.5 Sample Application: chatter.py</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node30.html">4.1 Subtransactions</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H1><A NAME="SECTION000500000000000000000">
4 Transactions and Versioning</A>
</H1>
<P>
<p><hr>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></a>
<UL CLASS="ChildLinks">
<LI><A href="node30.html">4.1 Subtransactions</a>
<LI><A href="node31.html">4.2 Undoing Changes</a>
<LI><A href="node32.html">4.3 Versions</a>
<LI><A href="node33.html">4.4 Multithreaded ZODB Programs</a>
</ul>
<!--End of Table of Child-Links-->
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node28.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node30.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node28.html">3.5 Sample Application: chatter.py</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node30.html">4.1 Subtransactions</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node4.html">
<LINK REL="previous" HREF="node2.html">
<LINK REL="up" HREF="node2.html">
<LINK REL="next" HREF="node4.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="1.1 What is the ZODB?">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>1.1 What is the ZODB?</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node2.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node2.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node4.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node2.html">1 Introduction</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node2.html">1 Introduction</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node4.html">1.2 OODBs vs. Relational</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000210000000000000000">
1.1 What is the ZODB?</A>
</H2>
<P>
The ZODB is a persistence system for Python objects. Persistent
programming languages provide facilities that automatically write
objects to disk and read them in again when they're required by a
running program. By installing the ZODB, you add such facilities to
Python.
<P>
It's certainly possible to build your own system for making Python
objects persistent. The usual starting points are the <tt class="module">pickle</tt>
module, for converting objects into a string representation, and
various database modules, such as the <tt class="module">gdbm</tt> or <tt class="module">bsddb</tt>
modules, that provide ways to write strings to disk and read them
back. It's straightforward to combine the <tt class="module">pickle</tt> module and
a database module to store and retrieve objects, and in fact the
<tt class="module">shelve</tt> module, included in Python's standard library, does
this.
<P>
The downside is that the programmer has to explicitly manage objects,
reading an object when it's needed and writing it out to disk when the
object is no longer required. The ZODB manages objects for you,
keeping them in a cache and writing them out if they haven't been
accessed in a while.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node2.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node2.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node4.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node2.html">1 Introduction</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node2.html">1 Introduction</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node4.html">1.2 OODBs vs. Relational</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node31.html">
<LINK REL="previous" HREF="node29.html">
<LINK REL="up" HREF="node29.html">
<LINK REL="next" HREF="node31.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="4.1 Subtransactions">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>4.1 Subtransactions</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node29.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node31.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node31.html">4.2 Undoing Changes</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000510000000000000000">
4.1 Subtransactions</A>
</H2>
<P>
Subtransactions can be created within a transaction. Each
subtransaction can be individually committed and aborted, but the
changes within a subtransaction are not truly committed until the
containing transaction is committed.
<P>
The primary purpose of subtransactions is to decrease the memory usage
of transactions that touch a very large number of objects. Consider a
transaction during which 200,000 objects are modified. All the
objects that are modified in a single transaction have to remain in
memory until the transaction is committed, because the ZODB can't
discard them from the object cache. This can potentially make the
memory usage quite large. With subtransactions, a commit can be be
performed at intervals, say, every 10,000 objects. Those 10,000
objects are then written to permanent storage and can be purged from
the cache to free more space.
<P>
To commit a subtransaction instead of a full transaction,
pass a true value to the <tt class="method">commit()</tt>
or <tt class="method">abort()</tt> method of the <tt class="class">Transaction</tt> object.
<P>
<div class="verbatim"><pre>
# Commit a subtransaction
get_transaction().commit(1)
# Abort a subtransaction
get_transaction().abort(1)
</pre></div>
<P>
A new subtransaction is automatically started on committing or
aborting the previous subtransaction.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node29.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node31.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node31.html">4.2 Undoing Changes</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node32.html">
<LINK REL="previous" HREF="node30.html">
<LINK REL="up" HREF="node29.html">
<LINK REL="next" HREF="node32.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="4.2 Undoing Changes">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>4.2 Undoing Changes</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node30.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node32.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node30.html">4.1 Subtransactions</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node32.html">4.3 Versions</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000520000000000000000">
4.2 Undoing Changes</A>
</H2>
<P>
Some types of <tt class="class">Storage</tt> support undoing a transaction even after
it's been committed. You can tell if this is the case by calling the
<tt class="method">supportsUndo()</tt> method of the <tt class="class">DB</tt> instance, which
returns true if the underlying storage supports undo. Alternatively
you can call the <tt class="method">supportsUndo()</tt> method on the underlying
storage instance.
<P>
If a database supports undo, then the <tt class="method">undoLog(<var>start</var>,
<var>end</var><big>[</big>, func<big>]</big>)</tt> method on the <tt class="class">DB</tt> instance returns
the log of past transactions, returning transactions between the times
<var>start</var> and <var>end</var>, measured in seconds from the epoch.
If present, <var>func</var> is a function that acts as a filter on the
transactions to be returned; it's passed a dictionary representing
each transaction, and only transactions for which <var>func</var> returns
true will be included in the list of transactions returned to the
caller of <tt class="method">undoLog()</tt>. The dictionary contains keys for
various properties of the transaction. The most important keys are
"<tt class="samp">id</tt>", for the transaction ID, and "<tt class="samp">time</tt>", for the time at
which the transaction was committed.
<P>
<div class="verbatim"><pre>
&gt;&gt;&gt; print storage.undoLog(0, sys.maxint)
[{'description': '',
'id': 'AzpGEGqU/0QAAAAAAAAGMA',
'time': 981126744.98,
'user_name': ''},
{'description': '',
'id': 'AzpGC/hUOKoAAAAAAAAFDQ',
'time': 981126478.202,
'user_name': ''}
...
</pre></div>
<P>
To store a description and a user name on a commit, get the current
transaction and call the <tt class="method">note(<var>text</var>)</tt> method to store a
description, and the
<tt class="method">setUser(<var>user_name</var>)</tt> method to store the user name.
While <tt class="method">setUser()</tt> overwrites the current user name and replaces
it with the new value, the <tt class="method">note()</tt> method always adds the text
to the transaction's description, so it can be called several times to
log several different changes made in the course of a single
transaction.
<P>
<div class="verbatim"><pre>
get_transaction().setUser('amk')
get_transaction().note('Change ownership')
</pre></div>
<P>
To undo a transaction, call the <tt class="method">DB.undo(<var>id</var>)</tt> method,
passing it the ID of the transaction to undo. If the transaction
can't be undone, a <tt class="exception">ZODB.POSException.UndoError</tt> exception
will be raised, with the message ``non-undoable
transaction''. Usually this will happen because later transactions
modified the objects affected by the transaction you're trying to
undo.
<P>
After you call <tt class="method">undo()</tt> you must commit the transaction for the
undo to actually be applied.
<A NAME="tex2html3"
HREF="#foot583"><SUP>3</SUP></A> There is one glitch in the undo process. The thread
that calls undo may not see the changes to the object until it calls
<tt class="method">Connection.sync()</tt> or commits another transaction.
<P>
<BR><HR><H4>Footnotes</H4>
<DL>
<DT><A NAME="foot583">... applied.</A><A
HREF="node31.html#tex2html3"><SUP>3</SUP></A></DT>
<DD>There are actually two different ways a storage can
implement the undo feature. Most of the storages that ship with ZODB
use the transactional form of undo described in the main text. Some
storages may use a non-transactional undo makes changes visible
immediately.
</DD>
</DL>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node30.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node32.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node30.html">4.1 Subtransactions</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node32.html">4.3 Versions</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node33.html">
<LINK REL="previous" HREF="node31.html">
<LINK REL="up" HREF="node29.html">
<LINK REL="next" HREF="node33.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="4.3 Versions">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>4.3 Versions</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node31.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node33.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node31.html">4.2 Undoing Changes</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node33.html">4.4 Multithreaded ZODB Programs</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000530000000000000000">
4.3 Versions</A>
</H2>
<P>
While many subtransactions can be contained within a single regular
transaction, it's also possible to contain many regular transactions
within a long-running transaction, called a version in ZODB
terminology. Inside a version, any number of transactions can be
created and committed or rolled back, but the changes within a version
are not made visible to other connections to the same ZODB.
<P>
Not all storages support versions, but you can test for versioning
ability by calling <tt class="method">supportsVersions()</tt> method of the
<tt class="class">DB</tt> instance, which returns true if the underlying storage
supports versioning.
<P>
A version can be selected when creating the <tt class="class">Connection</tt>
instance using the <tt class="method">DB.open(<big>[</big><var>version</var><big>]</big>)</tt> method.
The <var>version</var> argument must be a string that will be used as the
name of the version.
<P>
<div class="verbatim"><pre>
vers_conn = db.open(version='Working version')
</pre></div>
<P>
Transactions can then be committed and aborted using this versioned
connection. Other connections that don't specify a version, or
provide a different version name, will not see changes committed
within the version named "<tt class="samp">Working&nbsp;version</tt>". To commit or abort a
version, which will either make the changes visible to all clients or
roll them back, call the <tt class="method">DB.commitVersion()</tt> or
<tt class="method">DB.abortVersion()</tt> methods.
XXX what are the source and dest arguments for?
<P>
The ZODB makes no attempt to reconcile changes between different
versions. Instead, the first version which modifies an object will
gain a lock on that object. Attempting to modify the object from a
different version or from an unversioned connection will cause a
<tt class="exception">ZODB.POSException.VersionLockError</tt> to be raised:
<P>
<div class="verbatim"><pre>
from ZODB.POSException import VersionLockError
try:
get_transaction().commit()
except VersionLockError, (obj_id, version):
print ('Cannot commit; object %s '
'locked by version %s' % (obj_id, version))
</pre></div>
<P>
The exception provides the ID of the locked object, and the name of
the version having a lock on it.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node31.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node33.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node31.html">4.2 Undoing Changes</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node33.html">4.4 Multithreaded ZODB Programs</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="previous" HREF="node32.html">
<LINK REL="up" HREF="node29.html">
<LINK REL="next" HREF="node34.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="4.4 Multithreaded ZODB Programs">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>4.4 Multithreaded ZODB Programs</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node32.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node34.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node32.html">4.3 Versions</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000540000000000000000">
4.4 Multithreaded ZODB Programs</A>
</H2>
<P>
ZODB databases can be accessed from multithreaded Python programs.
The <tt class="class">Storage</tt> and <tt class="class">DB</tt> instances can be shared among
several threads, as long as individual <tt class="class">Connection</tt> instances
are created for each thread.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node32.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node29.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node34.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node32.html">4.3 Versions</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node29.html">4 Transactions and Versioning</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node38.html">
<LINK REL="previous" HREF="node29.html">
<LINK REL="up" HREF="zodb.html">
<LINK REL="next" HREF="node35.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="5 Related Modules">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>5 Related Modules</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node33.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node35.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node33.html">4.4 Multithreaded ZODB Programs</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node35.html">5.1 ZODB.PersistentMapping</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H1><A NAME="SECTION000600000000000000000">
5 Related Modules</A>
</H1>
<P>
The ZODB package includes a number of related modules that provide
useful data types such as BTrees.
<P>
<p><hr>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></a>
<UL CLASS="ChildLinks">
<LI><A href="node35.html">5.1 <tt class="module">ZODB.PersistentMapping</tt></a>
<LI><A href="node36.html">5.2 <tt class="module">ZODB.PersistentList</tt></a>
<LI><A href="node37.html">5.3 BTrees Package</a>
</ul>
<!--End of Table of Child-Links-->
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node33.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node35.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node33.html">4.4 Multithreaded ZODB Programs</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node35.html">5.1 ZODB.PersistentMapping</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node36.html">
<LINK REL="previous" HREF="node34.html">
<LINK REL="up" HREF="node34.html">
<LINK REL="next" HREF="node36.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="5.1 ZODB.PersistentMapping">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>5.1 ZODB.PersistentMapping</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node34.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node34.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node36.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node36.html">5.2 ZODB.PersistentList</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000610000000000000000">
5.1 <tt class="module">ZODB.PersistentMapping</tt></A>
</H2>
<P>
The <tt class="class">PersistentMapping</tt> class is a wrapper for mapping objects
that will set the dirty bit when the mapping is modified by setting or
deleting a key.
<P>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><a name="l2h-1"><tt class="function">PersistentMapping</tt></a></b>(</nobr></td>
<td><var>container = {}</var>)</td></tr></table>
<dd>
Create a <tt class="class">PersistentMapping</tt> object that wraps the
mapping object <var>container</var>. If you don't specify a
value for <var>container</var>, a regular Python dictionary is used.
</dl>
<P>
<tt class="class">PersistentMapping</tt> objects support all the same methods as
Python dictionaries do.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node34.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node34.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node36.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node36.html">5.2 ZODB.PersistentList</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node37.html">
<LINK REL="previous" HREF="node35.html">
<LINK REL="up" HREF="node34.html">
<LINK REL="next" HREF="node37.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="5.2 ZODB.PersistentList">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>5.2 ZODB.PersistentList</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node35.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node34.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node37.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node35.html">5.1 ZODB.PersistentMapping</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node37.html">5.3 BTrees Package</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000620000000000000000">
5.2 <tt class="module">ZODB.PersistentList</tt></A>
</H2>
<P>
The <tt class="class">PersistentList</tt> class is a wrapper for mutable sequence objects,
much as <tt class="class">PersistentMapping</tt> is a wrapper for mappings.
<P>
<dl><dt><table cellpadding="0" cellspacing="0"><tr valign="baseline">
<td><nobr><b><a name="l2h-2"><tt class="function">PersistentList</tt></a></b>(</nobr></td>
<td><var>initlist = []</var>)</td></tr></table>
<dd>
Create a <tt class="class">PersistentList</tt> object that wraps the
mutable sequence object <var>initlist</var>. If you don't specify a
value for <var>initlist</var>, a regular Python list is used.
</dl>
<P>
<tt class="class">PersistentList</tt> objects support all the same methods as
Python lists do.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node35.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node34.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node37.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node35.html">5.1 ZODB.PersistentMapping</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node37.html">5.3 BTrees Package</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="previous" HREF="node36.html">
<LINK REL="up" HREF="node34.html">
<LINK REL="next" HREF="node38.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="5.3 BTrees Package">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>5.3 BTrees Package</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node36.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node34.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node38.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node36.html">5.2 ZODB.PersistentList</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node38.html">A. Resources</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000630000000000000000">
5.3 BTrees Package</A>
</H2>
<P>
When programming with the ZODB, Python dictionaries aren't always what
you need. The most important case is where you want to store a very
large mapping. When a Python dictionary is accessed in a ZODB, the
whole dictionary has to be unpickled and brought into memory. If
you're storing something very large, such as a 100,000-entry user
database, unpickling such a large object will be slow. BTrees are a
balanced tree data structure that behave like a mapping but distribute
keys throughout a number of tree nodes. The nodes are stored in
sorted order. Nodes are then only unpickled and brought into memory
as they're accessed, so the entire tree doesn't have to occupy memory
(unless you really are touching every single key).
<P>
The BTrees package provides a large collection of related data
structures. There are variants of the data structures specialized to
handle integer values, which are faster and use less memory. There
are four modules that handle the different variants. The first two
letters of the module name specify the types of the keys and values in
mappings - O for any object and I for integer. The
<tt class="module">BTrees.IOBTree</tt> module provides a mapping that accepts integer
keys and arbitrary objects as values.
<P>
The four data structures provide by each module are a btree, a bucket,
a tree set, and a set. The btree and bucket types are mappings and
support all the usual mapping methods, e.g. <tt class="function">update()</tt> and
<tt class="function">keys()</tt>. The tree set and set types are similar to mappings
but they have no values; they support the methods that make sense for
a mapping with no keys, e.g. <tt class="function">keys()</tt> but not
<tt class="function">items()</tt>. The bucket and set types are the individual
building blocks for btrees and tree sets, respectively. A bucket or
set can be used when you are sure that it will have few elements. If
the data structure will grow large, you should use a btree or tree
set.
<P>
The four modules are named <tt class="module">OOBTree</tt>, <tt class="module">IOBTree</tt>,
<tt class="module">OIBTree</tt>, and <tt class="module">IIBTree</tt>. The two letter prefixes are
repeated in the data types names. The <tt class="module">BTrees.OOBTree</tt> module
defines the following types: <tt class="class">OOBTree</tt>, <tt class="class">OOBucket</tt>,
<tt class="class">OOSet</tt>, and <tt class="class">OOTreeSet</tt>.
<P>
The <tt class="function">keys()</tt>, <tt class="function">values()</tt>, and <tt class="function">items()</tt>
methods do not materialize a list with all of the data. Instead, they
return lazy sequences that fetch data from the BTree as needed. They
also support optional arguments to specify the minium and maximum
values to return.
<P>
A BTree object supports all the methods you would expect of a mapping
with a few extensions that exploit the fact that the keys are sorted.
The example below demonstrates how some of the methods work. The
extra methods re <tt class="function">minKey()</tt> and <tt class="function">maxKey()</tt>, which
find the minimum and maximum key value subject to an optional bound
argument, and <tt class="function">byValue()</tt>, which returns value, key pairs
in reversed sorted order subject to an optional minimum bound argument.
<P>
<div class="verbatim"><pre>
&gt;&gt;&gt; from BTrees.OOBTree import OOBTree
&gt;&gt;&gt; t = OOBTree()
&gt;&gt;&gt; t.update({ 1: "red", 2: "green", 3: "blue", 4: "spades" })
&gt;&gt;&gt; len(t)
4
&gt;&gt;&gt; t[2]
'green'
&gt;&gt;&gt; t.keys()
&lt;OOBTreeItems object at 0x40269098&gt;
&gt;&gt;&gt; [k for k in t.keys()] # use a listcomp to get a printable sequence
[1, 2, 3, 4]
&gt;&gt;&gt; [k for k in t.values()]
['red', 'green', 'blue', 'spades']
&gt;&gt;&gt; [k for k in t.values(1, 2)]
['red', 'green']
&gt;&gt;&gt; [k for k in t.values(2)]
['green', 'blue', 'spades']
&gt;&gt;&gt; t.byValue("glue") # all values &gt; "glue"
[('spades', 4), ('red', 1), ('green', 2)]
&gt;&gt;&gt; t.minKey(1.5)
2
</pre></div>
<P>
Each of the modules also defines some functions that operate on
BTrees - <tt class="function">difference()</tt>, <tt class="function">union()</tt>, and
<tt class="function">difference()</tt>. The <tt class="function">difference()</tt> function returns
a bucket, while the other two methods return a set.
If the keys are integers, then the module also defines
<tt class="function">multiunion()</tt>. If the values are integers, then the module
also defines <tt class="function">weightedIntersection()</tt> and
<tt class="function">weighterUnion()</tt>. The function doc strings describe each
function briefly.
<P>
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node36.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node34.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node38.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node36.html">5.2 ZODB.PersistentList</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node34.html">5 Related Modules</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node38.html">A. Resources</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node39.html">
<LINK REL="previous" HREF="node34.html">
<LINK REL="up" HREF="zodb.html">
<LINK REL="next" HREF="node39.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="A. Resources">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>A. Resources</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node37.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node39.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node37.html">5.3 BTrees Package</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H1><A NAME="SECTION000700000000000000000">
A. Resources</A>
</H1>
<P>
ZODB HOWTO, by Michel Pelletier:
<BR>
Goes into slightly more detail about the rules for writing applications using the ZODB.
<BR><a class="url" href="http://www.zope.org/Members/michel/HowTos/ZODB-How-To">http://www.zope.org/Members/michel/HowTos/ZODB-How-To</a>
<P>
Introduction to the Zope Object Database, by Jim Fulton:
<BR>
Goes into much greater detail, explaining advanced uses of the ZODB and
how it's actually implemented. A definitive reference, and highly recommended.
<BR><a class="url" href="http://www.python.org/workshops/2000-01/proceedings/papers/fulton/zodb3.html">http://www.python.org/workshops/2000-01/proceedings/papers/fulton/zodb3.html</a>
<P>
Persistent Programing with ZODB, by Jeremy Hylton and Barry Warsaw:
<BR>
Slides for a tutorial presented at the 10th Python conference. Covers
much of the same ground as this guide, with more details in some areas
and less in others.
<BR><a class="url" href="http://www.zope.org/Members/bwarsaw/ipc10-slides">http://www.zope.org/Members/bwarsaw/ipc10-slides</a>
<P>
Download link for ZEO:
<BR><a class="url" href="http://www.zope.org/Products/ZEO/">http://www.zope.org/Products/ZEO/</a>
<P>
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node37.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node39.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node37.html">5.3 BTrees Package</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" href="about.html">
<LINK REL="previous" HREF="node38.html">
<LINK REL="up" HREF="zodb.html">
<LINK REL="next" HREF="node40.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="B. GNU Free Documentation License">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>B. GNU Free Documentation License</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node38.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node40.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node38.html">A. Resources</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node40.html">Preamble</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H1><A NAME="SECTION000800000000000000000">
B. GNU Free Documentation License</A>
</H1>
<P>
Version 1.1, March 2000
<BR>
<P>
Copyright <SPAN CLASS="MATH"><IMG
WIDTH="20" HEIGHT="29" ALIGN="MIDDLE" BORDER="0"
SRC="img1.gif"
ALT="$\copyright$"></SPAN> 2000 Free Software Foundation, Inc.
<BR>
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
<BR>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
<P>
<p><hr>
<!--Table of Child-Links-->
<A NAME="CHILD_LINKS"><STRONG>Subsections</STRONG></a>
<UL CLASS="ChildLinks">
<LI><A href="node40.html">Preamble</a>
<LI><A href="node41.html">B..1 Applicability and Definitions</a>
<LI><A href="node42.html">B..2 Verbatim Copying</a>
<LI><A href="node43.html">B..3 Copying in Quantity</a>
<LI><A href="node44.html">B..4 Modifications</a>
<LI><A href="node45.html">B..5 Combining Documents</a>
<LI><A href="node46.html">B..6 Collections of Documents</a>
<LI><A href="node47.html">B..7 Aggregation With Independent Works</a>
<LI><A href="node48.html">B..8 Translation</a>
<LI><A href="node49.html">B..9 Termination</a>
<LI><A href="node50.html">B..10 Future Revisions of This Licence</a>
<LI><A href="node51.html">ADDENDUM: How to use this License for your documents</a>
</ul>
<!--End of Table of Child-Links-->
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node38.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="zodb.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node40.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node38.html">A. Resources</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="zodb.html">ZODB/ZEO Programming Guide</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node40.html">Preamble</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node5.html">
<LINK REL="previous" HREF="node3.html">
<LINK REL="up" HREF="node2.html">
<LINK REL="next" HREF="node5.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="1.2 OODBs vs. Relational DBs">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>1.2 OODBs vs. Relational DBs</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node3.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node2.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node5.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node3.html">1.1 What is the</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node2.html">1 Introduction</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node5.html">1.3 What is ZEO?</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000220000000000000000">
1.2 OODBs vs. Relational DBs</A>
</H2>
<P>
Another way to look at it is that the ZODB is a Python-specific
object-oriented database (OODB). Commercial object databases for C++
or Java often require that you jump through some hoops, such as using
a special preprocessor or avoiding certain data types. As we'll see,
the ZODB has some hoops of its own to jump through, but in comparison
the naturalness of the ZODB is astonishing.
<P>
Relational databases (RDBs) are far more common than OODBs.
Relational databases store information in tables; a table consists of
any number of rows, each row containing several columns of
information. (Rows are more formally called relations, which is where
the term ``relational database'' originates.)
<P>
Let's look at a concrete example. The example comes from my day job
working for the MEMS Exchange, in a greatly simplified version. The
job is to track process runs, which are lists of manufacturing steps
to be performed in a semiconductor fab. A run is owned by a
particular user, and has a name and assigned ID number. Runs consist
of a number of operations; an operation is a single step to be
performed, such as depositing something on a wafer or etching
something off it.
<P>
Operations may have parameters, which are additional information
required to perform an operation. For example, if you're depositing
something on a wafer, you need to know two things: 1) what you're
depositing, and 2) how much should be deposited. You might deposit
100 microns of silicon oxide, or 1 micron of copper.
<P>
Mapping these structures to a relational database is straightforward:
<P>
<div class="verbatim"><pre>
CREATE TABLE runs (
int run_id,
varchar owner,
varchar title,
int acct_num,
primary key(run_id)
);
CREATE TABLE operations (
int run_id,
int step_num,
varchar process_id,
PRIMARY KEY(run_id, step_num),
FOREIGN KEY(run_id) REFERENCES runs(run_id),
);
CREATE TABLE parameters (
int run_id,
int step_num,
varchar param_name,
varchar param_value,
PRIMARY KEY(run_id, step_num, param_name)
FOREIGN KEY(run_id, step_num)
REFERENCES operations(run_id, step_num),
);
</pre></div>
<P>
In Python, you would write three classes named <tt class="class">Run</tt>,
<tt class="class">Operation</tt>, and <tt class="class">Parameter</tt>. I won't present code for
defining these classes, since that code is uninteresting at this
point. Each class would contain a single method to begin with, an
<tt class="method">__init__</tt> method that assigns default values, such as 0 or
<code>None</code>, to each attribute of the class.
<P>
It's not difficult to write Python code that will create a <tt class="class">Run</tt>
instance and populate it with the data from the relational tables;
with a little more effort, you can build a straightforward tool,
usually called an object-relational mapper, to do this automatically.
(See
<a class="url" href="http://www.amk.ca/python/unmaintained/ordb.html">http://www.amk.ca/python/unmaintained/ordb.html</a> for a quick hack
at a Python object-relational mapper, and
<a class="url" href="http://www.python.org/workshops/1997-10/proceedings/shprentz.html">http://www.python.org/workshops/1997-10/proceedings/shprentz.html</a>for Joel Shprentz's more successful implementation of the same idea;
Unlike mine, Shprentz's system has been used for actual work.)
<P>
However, it is difficult to make an object-relational mapper
reasonably quick; a simple-minded implementation like mine is quite
slow because it has to do several queries to access all of an object's
data. Higher performance object-relational mappers cache objects to
improve performance, only performing SQL queries when they actually
need to.
<P>
That helps if you want to access run number 123 all of a sudden. But
what if you want to find all runs where a step has a parameter named
'thickness' with a value of 2.0? In the relational version, you have
two unappealing choices:
<P>
<OL>
<LI>Write a specialized SQL query for this case: <code>SELECT run_id
FROM operations WHERE param_name = 'thickness' AND param_value = 2.0</code>
<P>
If such queries are common, you can end up with lots of specialized
queries. When the database tables get rearranged, all these queries
will need to be modified.
<P>
</LI>
<LI>An object-relational mapper doesn't help much. Scanning
through the runs means that the the mapper will perform the required
SQL queries to read run #1, and then a simple Python loop can check
whether any of its steps have the parameter you're looking for.
Repeat for run #2, 3, and so forth. This does a vast
number of SQL queries, and therefore is incredibly slow.
<P>
</LI>
</OL>
<P>
An object database such as ZODB simply stores internal pointers from
object to object, so reading in a single object is much faster than
doing a bunch of SQL queries and assembling the results. Scanning all
runs, therefore, is still inefficient, but not grossly inefficient.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node3.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node2.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node5.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node3.html">1.1 What is the</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node2.html">1 Introduction</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node5.html">1.3 What is ZEO?</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node41.html">
<LINK REL="previous" HREF="node39.html">
<LINK REL="up" HREF="node39.html">
<LINK REL="next" HREF="node41.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="Preamble">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>Preamble</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node39.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node39.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node41.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node41.html">B..1 Applicability and Definitions</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000810000000000000000">
Preamble</A>
</H2>
<P>
The purpose of this License is to make a manual, textbook, or other
written document ``free'' in the sense of freedom: to assure everyone
the effective freedom to copy and redistribute it, with or without
modifying it, either commercially or noncommercially. Secondarily,
this License preserves for the author and publisher a way to get
credit for their work, while not being considered responsible for
modifications made by others.
<P>
This License is a kind of ``copyleft'', which means that derivative
works of the document must themselves be free in the same sense. It
complements the GNU General Public License, which is a copyleft
license designed for free software.
<P>
We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does. But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book. We recommend this License
principally for works whose purpose is instruction or reference.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node39.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node39.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node41.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node41.html">B..1 Applicability and Definitions</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node42.html">
<LINK REL="previous" HREF="node40.html">
<LINK REL="up" HREF="node39.html">
<LINK REL="next" HREF="node42.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="B..1 Applicability and Definitions">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>B..1 Applicability and Definitions</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node40.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node39.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node42.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node40.html">Preamble</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node42.html">B..2 Verbatim Copying</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000820000000000000000">
B..1 Applicability and Definitions</A>
</H2>
<P>
This License applies to any manual or other work that contains a
notice placed by the copyright holder saying it can be distributed
under the terms of this License. The ``Document'', below, refers to any
such manual or work. Any member of the public is a licensee, and is
addressed as ``you''.
<P>
A ``Modified Version'' of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
<P>
A ``Secondary Section'' is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject. (For example, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.) The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.
<P>
The ``Invariant Sections'' are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License.
<P>
The ``Cover Texts'' are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License.
<P>
A ``Transparent'' copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, whose contents can be viewed and edited directly and
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters. A copy made in an otherwise Transparent file
format whose markup has been designed to thwart or discourage
subsequent modification by readers is not Transparent. A copy that is
not ``Transparent'' is called ``Opaque''.
<P>
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, <SPAN CLASS="logo,LaTeX">L<SUP><SMALL>A</SMALL></SUP>T<SMALL>E</SMALL>X</SPAN>&nbsp;input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML designed for human modification. Opaque formats include
PostScript, PDF, proprietary formats that can be read and edited only
by proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML produced by some word processors for output
purposes only.
<P>
The ``Title Page'' means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page. For works in
formats which do not have any title page as such, ``Title Page'' means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node40.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node39.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node42.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node40.html">Preamble</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node42.html">B..2 Verbatim Copying</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="zodb.css" type='text/css'>
<link rel="first" href="zodb.html" title='ZODB/ZEO Programming Guide'>
<link rel="contents" href="contents.html" title="Contents"><link rel='last' href='about.html' title='About this document...'>
<link rel='help' href='about.html' title='About this document...'>
<LINK REL="next" HREF="node43.html">
<LINK REL="previous" HREF="node41.html">
<LINK REL="up" HREF="node39.html">
<LINK REL="next" HREF="node43.html">
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<meta name='aesop' content='information'>
<META NAME="description" CONTENT="B..2 Verbatim Copying">
<META NAME="keywords" CONTENT="zodb">
<META NAME="resource-type" CONTENT="document">
<META NAME="distribution" CONTENT="global">
<title>B..2 Verbatim Copying</title>
</head>
<body>
<DIV CLASS="navigation">
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node41.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node39.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node43.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node41.html">B..1 Applicability and Definitions</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node43.html">B..3 Copying in Quantity</A>
<br><hr>
</DIV>
<!--End of Navigation Panel-->
<H2><A NAME="SECTION000830000000000000000">
B..2 Verbatim Copying</A>
</H2>
<P>
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License. You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute. However, you may accept
compensation in exchange for copies. If you distribute a large enough
number of copies you must also follow the conditions in section 3.
<P>
You may also lend copies, under the same conditions stated above, and
you may publicly display copies.
<P>
<DIV CLASS="navigation">
<p><hr>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td><A HREF="node41.html"><img src='icons/previous.gif'
border='0' height='32' alt='Previous Page' width='32'></A></td>
<td><A HREF="node39.html"><img src='icons/up.gif'
border='0' height='32' alt='Up One Level' width='32'></A></td>
<td><A HREF="node43.html"><img src='icons/next.gif'
border='0' height='32' alt='Next Page' width='32'></A></td>
<td align="center" width="100%">ZODB/ZEO Programming Guide</td>
<td><A href="contents.html"><img src='icons/contents.gif'
border='0' height='32' alt='Contents' width='32'></A></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
<td><img src='icons/blank.gif'
border='0' height='32' alt='' width='32'></td>
</tr></table>
<b class="navlabel">Previous:</b> <a class="sectref" HREF="node41.html">B..1 Applicability and Definitions</A>
<b class="navlabel">Up:</b> <a class="sectref" HREF="node39.html">B. GNU Free Documentation</A>
<b class="navlabel">Next:</b> <a class="sectref" HREF="node43.html">B..3 Copying in Quantity</A>
<hr>
<span class="release-info">Release 0.04, documentation updated on 17 January 2003.</span>
</DIV>
<!--End of Navigation Panel-->
</BODY>
</HTML>
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment