[Twisted-Python] Re: Re: Re: Re: rewrite of flow.py completed
Philippe Lafoucrière
lafou at wanadoo.fr
Thu Apr 17 06:49:54 EDT 2003
Clark C. Evans wrote:
> On Wed, Apr 16, 2003 at 02:03:06PM +0200, Philippe Lafoucrière wrote:
> | I solved the problem. It was a missing import (QueryIterator). But any
> | exception is raised when using flow. It's too hard to debug, even for
> | few lines of code.
>
> Yes, I know... better exception handling is next on me list.
>
> ;) Clark
Thank you for the documentation Clark. Here's a little doc patch that just
add some titles and a new part on QueryIterator (which is not good at all
:( )
Index: flow.html
===================================================================
RCS file: /cvs/Twisted/sandbox/flow.html,v
retrieving revision 1.3
diff -u -r1.3 flow.html
--- flow.html 17 Apr 2003 08:00:11 -0000 1.3
+++ flow.html 17 Apr 2003 10:51:09 -0000
@@ -63,10 +63,10 @@
than blocking, the entire state of the iterator chain must be saved so that
it can be resumed later. This is what the flow module does.</p>
-<h3>Iterators and Wraps</h3>
+<h3>Iterators and generators</h3>
<p>An iterator is basically an object which produces a sequence of values.
-Python's iterators are simply objects with an <code>__iter__()</code>
+Python's iterators are simply objects with an <code>__iter__()</code>
member function which returns an object (usually itself) which has a
<code>next()</code> member function. The <code>next()</code> method is
then invoked till it raises a <code>StopIteration</code> exception.
@@ -206,6 +206,8 @@
</pre>
+<h3>Wrapping Iterator</h3>
+
<p>The problem with this approach, is that a producer could potentially
block, and if it did, the entire process could potentially stop servicing
other requests. Thus, some mechanism for pausing the flow and rebuilding
@@ -259,11 +261,13 @@
</pre>
-<p>This seems like quite the effort, wrapping each iterator and
+<h3>Cooperate</h3>
+
+<p>This seems like quite the effort, wrapping each iterator and
then having to alter the calling sequence. Why? The answer is
that it allows for a <code>flow.Cooperate</code> object to be
returned. When this happens, the entire call chain can be
-moved off the stack so that other flows can proceed. For
+moved off the stack so that other flows can proceed. For
flow.Iterator (which blocks), the implementation of Cooperate
simply puts the call chain to sleep</p>
@@ -281,10 +285,13 @@
# 3
</pre>
+
+<h3>Merging Iterators in one flow</h3>
+
<p>Perhaps a more clear example can be found when using the
Merge function in Flow. This simply zips two or more wrapped
iterators together, without blocking one or the other. In the
-example below, the <code>States</code> iterator isn't blocked
+example below, the <code>States</code> iterator isn't blocked
by the <code>Counter</code> iterator.
</p>
@@ -324,7 +331,7 @@
<code>reactor.callLater</code> and <code>internet.defer.Deferred</code>
mechanism, things are very nice. In the example below, the first two
items in the list are produced (although they arn't delivered yet),
-other events in the reactor are allowed to proceed, and then the
+other events in the reactor are allowed to proceed, and then the
last item in the list is produced.</p>
@@ -333,7 +340,7 @@
from twisted.internet import reactor
import flow
-def prn(x):
+def prn(x):
print x
d = flow.Deferred([1,2,flow.Cooperate(1),3])
d.addCallback(prn)
@@ -344,6 +351,48 @@
# [1,2,3]
</pre>
+<h3>Using database connexion to prodive data</h3>
+
+<p>
+Of course, Flow allows to use ConnectionPools to provide data.<br />
+QueryIterator is a simple Iterator which provides data from a database. Is
uses <code>twisted.enterprise.adbapi</code>
+connectionPools, and a query to fetch data. QueryIterator must be used with
a deferred execution.
+</p>
+
+<pre class="python">
+from __future__ import generators
+from twisted.enterprise import adbapi
+from sandbox.flow import QueryIterator
+from twisted.internet import reactor
+
+import flow
+
+dbpool = adbapi.ConnectionPool("MySQLdb",host='localhost',
db='ADB',user='AUSER',passwd='APASSWD')
+sql = """SELECT name FROM mytable LIMIT 0,3"""
+
+def consumer():
+ query = flow.Wrap(QueryIterator(dbpool, sql))
+ while 1:
+ try:
+ yield query
+ if query.stop: break
+ print "Processed result : ",query.result
+ except flow.StopIteration: print "-- Finished --"
+
+from twisted.internet import reactor
+def finish(result): print "Final result : ", result
+f = flow.Deferred(consumer())
+f.addBoth(finish)
+reactor.callLater(1,reactor.stop)
+reactor.run()
+
+# prints
+# Processed result : ('SMITH',)
+# Processed result : ('JOHN',)
+# Processed result : ('BOB',)
+# Final result : []
+
+</pre>
</body>
</html>
More information about the Twisted-Python
mailing list