<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Terry Jones &#187; twisted</title>
	<atom:link href="http://blogs.fluidinfo.com/terry/category/python/twisted-python/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogs.fluidinfo.com/terry</link>
	<description>Random thoughts on tech, books, programming, etc.</description>
	<lastBuildDate>Sat, 21 Jan 2012 06:18:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>txdpce: a Twisted class for deferred parallel command execution</title>
		<link>http://blogs.fluidinfo.com/terry/2011/07/12/txdpce-a-twisted-class-for-deferred-parallel-command-execution/</link>
		<comments>http://blogs.fluidinfo.com/terry/2011/07/12/txdpce-a-twisted-class-for-deferred-parallel-command-execution/#comments</comments>
		<pubDate>Tue, 12 Jul 2011 12:43:35 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=844</guid>
		<description><![CDATA[I just uploaded a simple Twisted Python class, txdpce, to Launchpad. It&#8217;s designed for situations where you have multiple ways of obtaining a function result and you want to try them all in parallel and return the result from the fastest function. A typical case is that you can either compute a result via a [...]]]></description>
			<content:encoded><![CDATA[<p>I just <a href="https://launchpad.net/txdpce">uploaded</a> a simple <a href="http://twistedmatrix.com">Twisted</a> <a href="http://www.python.org">Python</a> class, txdpce, to Launchpad. It&#8217;s designed for situations where you have multiple ways of obtaining a function result and you want to try them all in parallel and return the result from the fastest function. A typical case is that you can either compute a result via a network call or try to get it out of a cache (perhaps also via a network call, to memcached). You might also be able to compute it locally, etc.</p>
<p>Things can be more complicated than provided for here, of course. E.g., you might like to cache the result of a local call (if it finishes first or if the cache lookup fails). The txdpce class is supposed to be a simple demonstration. I wrote it for a bit of fun this morning and also because it&#8217;s yet another nice example of how you can click together the building blocks of Twisted to form increasingly sophisticated classes.</p>
<p>Here&#8217;s the class. You&#8217;ll find a test suite <a href="https://launchpad.net/txdpce">at the Launchpad site</a>. You can download the code using bzr via <tt>bzr branch lp:txdpce</tt>.</p>
<p><code></p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">from</span> twisted.<span class="me1">internet</span> <span class="kw1">import</span> defer<br />
<span class="kw1">from</span> twisted.<span class="me1">python</span> <span class="kw1">import</span> failure</p>
<p>
<span class="kw1">class</span> ParallelCommandException<span class="br0">&#40;</span><span class="kw2">Exception</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">pass</span></p>
<p>
<span class="kw1">class</span> DeferredParallelCommandExecutor<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Provides a mechanism for the execution of a command by multiple methods,<br />
&nbsp; &nbsp; returning the result from the one that finishes first.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._functions = <span class="br0">&#91;</span><span class="br0">&#93;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> registerFunction<span class="br0">&#40;</span><span class="kw2">self</span>, func<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Add func to the list of functions that will be run when execute is<br />
&nbsp; &nbsp; &nbsp; &nbsp; called.</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; @param func: A callable that should be run when execute is called.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._functions.<span class="me1">append</span><span class="br0">&#40;</span>func<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> execute<span class="br0">&#40;</span><span class="kw2">self</span>, *args, **kwargs<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Run all the functions in self._functions on the given arguments and<br />
&nbsp; &nbsp; &nbsp; &nbsp; keyword arguments.</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; @param args: Arguments to pass to the registered functions.</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; @param kwargs: Keyword arguments to pass to the registered functions.</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; @raise RuntimeError: if no execution functions have been registered.</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; @return: A C{Deferred} that fires when the first of the functions<br />
&nbsp; &nbsp; &nbsp; &nbsp; finishes.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> <span class="kw2">self</span>._functions:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">raise</span> <span class="kw2">RuntimeError</span><span class="br0">&#40;</span><span class="st0">'No execution functions have been registered.'</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; deferreds = <span class="br0">&#91;</span>defer.<span class="me1">maybeDeferred</span><span class="br0">&#40;</span>func, *args, **kwargs<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">for</span> func <span class="kw1">in</span> <span class="kw2">self</span>._functions<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; d = defer.<span class="me1">DeferredList</span><span class="br0">&#40;</span>deferreds, fireOnOneCallback=<span class="nu0">1</span>, consumeErrors=<span class="nu0">1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">addCallback</span><span class="br0">&#40;</span><span class="kw2">self</span>._done, deferreds<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> d</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> _done<span class="br0">&#40;</span><span class="kw2">self</span>, deferredListResult, deferreds<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Process the result of the C{DeferredList} execution of all the<br />
&nbsp; &nbsp; &nbsp; &nbsp; functions in self._functions. If result is a tuple, it's the result<br />
&nbsp; &nbsp; &nbsp; &nbsp; of a successful function, in which case we cancel all the other<br />
&nbsp; &nbsp; &nbsp; &nbsp; deferreds (none of which has finished yet) and give back the<br />
&nbsp; &nbsp; &nbsp; &nbsp; result. &nbsp;Otherwise, all the function calls must have failed (since<br />
&nbsp; &nbsp; &nbsp; &nbsp; we passed fireOnOneCallback=True to the C{DeferredList} and we<br />
&nbsp; &nbsp; &nbsp; &nbsp; return a L{ParallelCommandException} containing the failures.</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; @param deferredListResult: The result of a C{DeferredList} returned<br />
&nbsp; &nbsp; &nbsp; &nbsp; by self.execute firing.</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; @param deferreds: A list of deferreds for other functions that were<br />
&nbsp; &nbsp; &nbsp; &nbsp; trying to compute the result.</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; @return: Either the result of the first function to successfully<br />
&nbsp; &nbsp; &nbsp; &nbsp; compute the result or a C{failure.Failure} containing a<br />
&nbsp; &nbsp; &nbsp; &nbsp; L{ParallelCommandException} with a list of the failures from all<br />
&nbsp; &nbsp; &nbsp; &nbsp; functions that tried to get the result.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">isinstance</span><span class="br0">&#40;</span>deferredListResult, <span class="kw2">tuple</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># A tuple result means the DeferredList fired with a successful</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># result. &nbsp;Cancel all other deferreds and return the result.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result, index = deferredListResult<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> i <span class="kw1">in</span> <span class="kw2">range</span><span class="br0">&#40;</span><span class="kw2">len</span><span class="br0">&#40;</span><span class="kw2">self</span>._functions<span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> i != index:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; deferreds<span class="br0">&#91;</span>i<span class="br0">&#93;</span>.<span class="me1">cancel</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> result<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># All the deferreds failed. Return a list of all the failures.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; failures = <span class="br0">&#91;</span>fail <span class="kw1">for</span> <span class="br0">&#40;</span>result, fail<span class="br0">&#41;</span> <span class="kw1">in</span> deferredListResult<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> failure.<span class="me1">Failure</span><span class="br0">&#40;</span>ParallelCommandException<span class="br0">&#40;</span>failures<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2011/07/12/txdpce-a-twisted-class-for-deferred-parallel-command-execution/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A resizable dispatch queue for Twisted</title>
		<link>http://blogs.fluidinfo.com/terry/2011/06/27/a-resizable-dispatch-queue-for-twisted/</link>
		<comments>http://blogs.fluidinfo.com/terry/2011/06/27/a-resizable-dispatch-queue-for-twisted/#comments</comments>
		<pubDate>Mon, 27 Jun 2011 15:19:27 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=830</guid>
		<description><![CDATA[In December 2009 I posted to the Twisted mailing list about what I called a Resizable Dispatch Queue. I&#8217;ve just spent some time making a new version that&#8217;s much improved. You can pick up the new version via pip install txrdq, from PyPI, or from the txRDQ project page on Launchpad. Here&#8217;s the example use [...]]]></description>
			<content:encoded><![CDATA[<p>In December 2009 I <a href="http://twistedmatrix.com/pipermail/twisted-python/2009-December/021127.html">posted</a> to the <a href="http://twistedmatrix.com">Twisted</a> mailing list about what I called a Resizable Dispatch Queue.  I&#8217;ve just spent some time making a new version that&#8217;s much improved. You can pick up the new version via <tt>pip install txrdq</tt>, from <a href="http://pypi.python.org/pypi/txRDQ">PyPI</a>, or from <a href="https://launchpad.net/txrdq">the txRDQ project page on Launchpad</a>. Here&#8217;s the example use case, taken from <a href="http://twistedmatrix.com/pipermail/twisted-python/2009-December/021127.html">my original posting</a>:</p>
<blockquote><p>You want to write a server with a web interface that allows people to enter their phone number so you can send them an SMS. You anticipate lots of people will use the service. But sending SMS messages is quite slow, and the company that you ship those jobs off to is concerned that you&#8217;ll overrun their service (or maybe they have an API limit, etc). So you need to queue up jobs locally and send them off at a certain rate. You&#8217;d like to be able to adjust that rate up or down. You also want to be able to shut your service down cleanly (i.e., not in the middle of a task), and when you restart it you want to be able to re-queue the jobs that were queued last time but which hadn&#8217;t gone out.</p></blockquote>
<p>To make the example more concrete, suppose your function that sends the SMS is called <tt>sendSMS</tt> and that it takes a <tt>(number, message)</tt> tuple argument. Here are some of the kinds of things you can do:</p>
<p><code></p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">from</span> txrdq.<span class="me1">rdq</span> <span class="kw1">import</span> ResizableDispatchQueue</p>
<p><span class="co1"># Create a queue that will allow 5 simultaneous underway jobs.</span><br />
rdq = ResizableDispatchQueue<span class="br0">&#40;</span>sendSMS, <span class="nu0">5</span><span class="br0">&#41;</span></p>
<p><span class="co1"># Later... send off some SMS messages.</span><br />
d1 = rdq.<span class="me1">put</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">2127399921</span>, <span class="st0">'Hello...'</span><span class="br0">&#41;</span>, priority=<span class="nu0">5</span><span class="br0">&#41;</span><br />
d1.<span class="me1">addCallback</span><span class="br0">&#40;</span>...<span class="br0">&#41;</span></p>
<p>d2 = rdq.<span class="me1">put</span><span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">5052929919</span>, <span class="st0">'Test...'</span><span class="br0">&#41;</span>, priority=<span class="nu0">5</span><span class="br0">&#41;</span><br />
d2.<span class="me1">addCallback</span><span class="br0">&#40;</span>...<span class="br0">&#41;</span></p>
<p><span class="co1"># Cancel the second job</span><br />
d2.<span class="me1">cancel</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="co1"># Widen the outgoing pipeline to 10 simultaneous jobs.</span><br />
rdq.<span class="me1">width</span> = <span class="nu0">10</span></p>
<p><span class="co1"># We're dispatching jobs too fast, turn it down a little.</span><br />
rdq.<span class="me1">width</span> = <span class="nu0">7</span></p>
<p><span class="co1"># Get a copy of the list of pending jobs.</span><br />
jobs = rdq.<span class="me1">pending</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="co1"># Cancel one of the pending jobs from the jobs list.</span><br />
job.<span class="me1">cancel</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="co1"># Reprioritize one of the pending jobs from the jobs list.</span><br />
rdq.<span class="me1">reprioritize</span><span class="br0">&#40;</span>job, <span class="nu0">-1</span><span class="br0">&#41;</span></p>
<p><span class="co1"># Arrange to increase the number of jobs in one hour.</span><br />
reactor.<span class="me1">callLater</span><span class="br0">&#40;</span><span class="nu0">3600</span>, rdq.<span class="me1">setWidth</span>, <span class="nu0">20</span><span class="br0">&#41;</span></p>
<p><span class="co1"># Pause processing.</span><br />
rdq.<span class="me1">pause</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="co1"># Resume processing, with a new width of 8.</span><br />
rdq.<span class="me1">resume</span><span class="br0">&#40;</span><span class="nu0">8</span><span class="br0">&#41;</span></p>
<p><span class="co1"># Shutdown. Wait for any underway jobs to complete, and save</span><br />
<span class="co1"># the list of jobs not yet processed.</span></p>
<p><span class="kw1">def</span> saveJobs<span class="br0">&#40;</span>jobs<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw3">pickle</span>.<span class="me1">dump</span><span class="br0">&#40;</span>jobs, ...<span class="br0">&#41;</span></p>
<p>d = rdq.<span class="me1">stop</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d.<span class="me1">addCallback</span><span class="br0">&#40;</span>saveJobs<span class="br0">&#41;</span><br />
&nbsp;</div>
<p></code></p>
<p>I&#8217;ve come up with many uses for this class over the last 18 months, and have quite often recommended it to people on the #twisted IRC channel. Other examples include fetching a large number of URLs in a controlled way, making many calls to the <a href="http://twitter.com">Twitter</a> API, etc.</p>
<p>Usage of the class is very simple. You create the dispatch queue, giving it a function that will be called to process all jobs. Then you just <tt>put</tt> job arguments as fast as you like. Each call to <tt>put</tt> gets you a Twisted Deferred instance. If your function runs successfully on the argument, the deferred will call back with an instance of <tt><a href="http://bazaar.launchpad.net/~terrycojones/txrdq/trunk/view/head:/txrdq/job.py">txrdq.job.Job</a></tt>. The job contains information about when it was queued, when it was launched, when it stopped, and of course the result of the function.  If your function hits an error or the job is canceled (by calling <tt>cancel</tt> on the deferred), the deferred will errback and the failure will again contain a job instance with the details.</p>
<p>It&#8217;s also useful to have an admin interface to the queue, so calls such as <tt>pending</tt> and <tt>underway</tt> are provided. These return lists of job instances. You can call <tt>cancel</tt> on a job instance too. You can reprioritize jobs. And you can pause processing or shut the queue down cleanly.</p>
<p>The code also contains an independently useful Twisted classes called <tt><a href="http://bazaar.launchpad.net/~terrycojones/txrdq/trunk/view/head:/txrdq/dpq.py">DeferredPriorityQueue</a></tt> (which I plan to write about), and <tt>DeferredPool</tt> (which <a href="http://blogs.fluidinfo.com/terry/2011/06/10/graceful-shutdown-of-a-twisted-service-with-outstanding-deferreds/">I described earlier</a>).</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2011/06/27/a-resizable-dispatch-queue-for-twisted/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to asynchronously exchange a dictionary using Twisted deferreds</title>
		<link>http://blogs.fluidinfo.com/terry/2011/06/10/how-to-asynchronously-exchange-a-dictionary-using-twisted-deferreds/</link>
		<comments>http://blogs.fluidinfo.com/terry/2011/06/10/how-to-asynchronously-exchange-a-dictionary-using-twisted-deferreds/#comments</comments>
		<pubDate>Fri, 10 Jun 2011 17:13:52 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=806</guid>
		<description><![CDATA[Here&#8217;s a fun class that I can&#8217;t think of a good use for :-) But I like its simplicity and it&#8217;s another illustration of what I like to call asynchronous data structures. Suppose you have a producer who&#8217;s building a dictionary and a consumer who wants to look things up in it. The producer is [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a fun class that I can&#8217;t think of a good use for :-)  But I like its simplicity and it&#8217;s another illustration of what I like to call <a href="http://blogs.fluidinfo.com/terry/2010/07/23/asynchronous-data-structures-with-twisted-deferreds/">asynchronous data structures</a>.</p>
<p>Suppose you have a producer who&#8217;s building a dictionary and a consumer who wants to look things up in it. The producer is working at their own pace, making new dictionary entries in whatever work order that suits them, and the consumer is requesting dictionary items in whatever order they need them. The two orders are obviously extremely unlikely to be the same if the dictionary is of non-trivial size.  How do you write an asynchronous server (or data structure) that sits between the producer and consumer?</p>
<p>Yes, it&#8217;s far fetched, perhaps, but here&#8217;s a simple asynchronous dictionary class that lets you do it gracefully:</p>
<p><code></p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">from</span> <span class="kw3">collections</span> <span class="kw1">import</span> defaultdict<br />
<span class="kw1">from</span> twisted.<span class="me1">internet</span> <span class="kw1">import</span> defer</p>
<p><span class="kw1">class</span> DeferredDict<span class="br0">&#40;</span><span class="kw2">dict</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, *args, **kwargs<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._deferreds = defaultdict<span class="br0">&#40;</span><span class="kw2">set</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">dict</span>.<span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, *args, **kwargs<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__getitem__</span><span class="br0">&#40;</span><span class="kw2">self</span>, item<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> defer.<span class="me1">succeed</span><span class="br0">&#40;</span><span class="kw2">dict</span>.<span class="kw4">__getitem__</span><span class="br0">&#40;</span><span class="kw2">self</span>, item<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyError</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._deferreds<span class="br0">&#91;</span>item<span class="br0">&#93;</span>.<span class="me1">add</span><span class="br0">&#40;</span>d<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> d</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__setitem__</span><span class="br0">&#40;</span><span class="kw2">self</span>, item, value<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> item <span class="kw1">in</span> <span class="kw2">self</span>._deferreds:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> d <span class="kw1">in</span> <span class="kw2">self</span>._deferreds<span class="br0">&#91;</span>item<span class="br0">&#93;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">callback</span><span class="br0">&#40;</span>value<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">del</span> <span class="kw2">self</span>._deferreds<span class="br0">&#91;</span>item<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">dict</span>.<span class="kw4">__setitem__</span><span class="br0">&#40;</span><span class="kw2">self</span>, item, value<span class="br0">&#41;</span><br />
&nbsp;</div>
<p></code></p>
<p>When a consumer tries to get an element from the dictionary, they always get a deferred. The deferred will fire with the value from the dictionary when (if) it becomes available. Of course if the value is already known, they get it in a deferred that has already fired (via <tt>succeed</tt>). When the producer puts an element into the dictionary, any consumer deferreds that were waiting on that element&#8217;s value are given the value.</p>
<p>Note that a <tt>__delitem__</tt> isn&#8217;t needed, we just inherit that from <tt>dict</tt>. If a non-existent item is deleted, you get the normal dictionary behavior (a <tt>KeyError</tt>). If the item does exist, that means the list of waiting deferreds on that item is empty (the fact the item exists means any waiting deferreds for the item have all been fired and that that item in the <tt>self._deferreds</tt> dictionary was deleted), so we can just let the dictionary class delete the item, as usual.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2011/06/10/how-to-asynchronously-exchange-a-dictionary-using-twisted-deferreds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Graceful shutdown of a Twisted service with outstanding deferreds</title>
		<link>http://blogs.fluidinfo.com/terry/2011/06/10/graceful-shutdown-of-a-twisted-service-with-outstanding-deferreds/</link>
		<comments>http://blogs.fluidinfo.com/terry/2011/06/10/graceful-shutdown-of-a-twisted-service-with-outstanding-deferreds/#comments</comments>
		<pubDate>Fri, 10 Jun 2011 16:42:24 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=797</guid>
		<description><![CDATA[I&#8217;ve been spending a bit of time thinking again about queues and services. I wrote a Twisted class in 2009 to maintain a resizable dispatch queue (code in Launchpad, description on the Twisted mailing list). For this post I&#8217;ve pulled out (and simplified slightly) one of its helper classes, a DeferredPool. This simple class maintains [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been spending a bit of time thinking again about queues and services. I wrote a <a href="http://twistedmatrix.com">Twisted</a> class in 2009 to maintain a resizable dispatch queue (<a href="https://launchpad.net/txrdq">code in Launchpad</a>, <a href="http://twistedmatrix.com/pipermail/twisted-python/2009-December/021127.html">description on the Twisted mailing list</a>). For this post I&#8217;ve pulled out (and simplified slightly) one of its helper classes, a DeferredPool.</p>
<p>This simple class maintains a set of deferreds and gives you a mechanism to get a deferred that will fire when (if!) the size of the set ever drops to zero. This is useful because it can be used to gracefully shut down a service that has a bunch of outstanding requests in flight. For each incoming request (that&#8217;s handled via a deferred), you add the deferred to the pool. When a signal arrives to tell the service to stop, you stop taking new requests and ask the pool for a deferred that will fire when all the outstanding deferreds are done, then you exit. This can all be done elegantly in Twisted, the last part by having the stopService method return the deferred you get back from the pool (perhaps after you add more cleanup callbacks to it).</p>
<p>Here&#8217;s the code:</p>
<p><code></p>
<div class="dean_ch" style="white-space: nowrap;">
<p><span class="kw1">from</span> twisted.<span class="me1">internet</span> <span class="kw1">import</span> defer</p>
<p><span class="kw1">class</span> DeferredPool<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Maintains a pool of not-yet-fired deferreds and gives a mechanism to<br />
&nbsp; &nbsp; request a deferred that fires when the pool size goes to zero.&quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._pool = <span class="kw2">set</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._waiting = <span class="br0">&#91;</span><span class="br0">&#93;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> _fired<span class="br0">&#40;</span><span class="kw2">self</span>, result, d<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Callback/errback each pooled deferred runs when it fires. The<br />
&nbsp; &nbsp; &nbsp; &nbsp; deferred first removes itself from the pool. If the pool is then<br />
&nbsp; &nbsp; &nbsp; &nbsp; empty, fire all the waiting deferreds (which were returned by<br />
&nbsp; &nbsp; &nbsp; &nbsp; notifyWhenEmpty).&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._pool.<span class="me1">remove</span><span class="br0">&#40;</span>d<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> <span class="kw2">self</span>._pool:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; waiting, <span class="kw2">self</span>._waiting = <span class="kw2">self</span>._waiting, <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> waiter <span class="kw1">in</span> waiting:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; waiter.<span class="me1">callback</span><span class="br0">&#40;</span><span class="kw2">None</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> result</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> add<span class="br0">&#40;</span><span class="kw2">self</span>, d<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Add a deferred to the pool.&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">addBoth</span><span class="br0">&#40;</span><span class="kw2">self</span>._fired, d<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._pool.<span class="me1">add</span><span class="br0">&#40;</span>d<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> notifyWhenEmpty<span class="br0">&#40;</span><span class="kw2">self</span>, testImmediately=<span class="kw2">True</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Return a deferred that fires (with None) when the pool empties.<br />
&nbsp; &nbsp; &nbsp; &nbsp; If testImmediately is True and the pool is empty, return an already<br />
&nbsp; &nbsp; &nbsp; &nbsp; fired deferred (via succeed).&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> testImmediately <span class="kw1">and</span> <span class="kw1">not</span> <span class="kw2">self</span>._pool:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> defer.<span class="me1">succeed</span><span class="br0">&#40;</span><span class="kw2">None</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._waiting.<span class="me1">append</span><span class="br0">&#40;</span>d<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> d<br />
&nbsp;</div>
<p></code></p>
<p>As usual I&#8217;m posting this example because I find Twisted&#8217;s deferreds so elegant. Here are a few comments on the above that might help you understand deferreds better.</p>
<p>A frequent pattern when creating and managing deferreds is that you can add callbacks and errbacks to them yourself to transparently do some housekeeping when they fire. In this case, for each deferred passed to add, I&#8217;m adding a callback and an errback that will run <tt>self._fired</tt> when the deferred fires. The first thing that method does is take the deferred out of the pool of outstanding deferreds. So the deferred itself cleans up the pool. It does that transparently, by which I mean that the call/errback function (<tt>self._fired</tt>) always returns whatever result it was passed. It&#8217;s on both the callback and errback chains of the deferred and has no effect on the result. The deferred may already have call/errbacks on it when it is passed to <tt>add</tt>, and it may have them added to it after <tt>add</tt> is done. Whoever created and is otherwise using the deferred will be none the wiser and is in no way affected.</p>
<p>When a deferred in the pool fires, it also checks to see if the pool size is zero and if there are any deferreds waiting to be informed of that. If so, it fires all the waiting deferreds and empties the list of waiting deferreds. This doesn&#8217;t mean the action is necessarily over. More deferreds can be added, more waiters can be added, etc. The pool size can go to zero again and if there are no waiters are waiting, no big deal, etc.</p>
<p>It&#8217;s easy to add functionality to e.g., record what time deferreds were added, provide stats, allow outstanding deferreds to be cancelled, add notifications when high/low water marks are reached, etc. But that&#8217;s enough for now. Feel free to ask questions below.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2011/06/10/graceful-shutdown-of-a-twisted-service-with-outstanding-deferreds/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Twisted&#8217;s Deferred class chainDeferred method is too simplistic?</title>
		<link>http://blogs.fluidinfo.com/terry/2010/08/14/twisteds-deferred-class-chaindeferred-method-is-too-simplistic/</link>
		<comments>http://blogs.fluidinfo.com/terry/2010/08/14/twisteds-deferred-class-chaindeferred-method-is-too-simplistic/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 01:25:53 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=683</guid>
		<description><![CDATA[I think it&#8217;s worth spending some time thinking about whether chainDeferred in twisted.internet.defer.Deferred is too simplistic. I&#8217;ve thought for a while that it could be more helpful in preventing people from doing unintended things and/or cause fewer surprises (e.g., see point #1 in this post). Those are smaller things that people can obviously live with. [...]]]></description>
			<content:encoded><![CDATA[<p>I think it&#8217;s worth spending some time thinking about whether chainDeferred in <a href="http://twistedmatrix.com/trac/browser/trunk/twisted/internet/defer.py">twisted.internet.defer.Deferred</a> is too simplistic. I&#8217;ve thought for a while that it could be more helpful in preventing people from doing unintended things and/or cause fewer surprises (e.g., see point #1 <a href="http://twistedmatrix.com/pipermail/twisted-python/2009-March/019298.html">in this post</a>).</p>
<p>Those are smaller things that people can obviously live with. But a more important one concerns deferred cancellation. See uncalled.py below for why.</p>
<p>Here are five examples of chainDeferred behavior that I think could be better. In an attempt to fix these, I made a few changes to a copy of defer.py (immodestly called tdefer.py, sorry) which you can grab, with runnable examples, <a href="http://github.com/fluidinfo/chainDeferredExamples">here</a>. The tdefer.py code is meant as a suggested approach. I doubt that it&#8217;s bulletproof.</p>
<p>Here are the examples.</p>
<p><strong>boom1.py:</strong></p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="co1"># Normal deferreds: this raises defer.AlreadyCalledError because</span><br />
<span class="co1"># the callback of d1 causes the callback of d2 to be called, but d2 has</span><br />
<span class="co1"># already been cancelled (and hence called).</span></p>
<p><span class="co1"># With tdefer.py: there is no error because d1.callback will not call</span><br />
<span class="co1"># d2 as it has already been cancelled.</span></p>
<p><span class="kw1">def</span> printCancel<span class="br0">&#40;</span>fail<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; fail.<span class="me1">trap</span><span class="br0">&#40;</span>defer.<span class="me1">CancelledError</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;cancelled&#8217;</span></p>
<p><span class="kw1">def</span> canceller<span class="br0">&#40;</span>d<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;cancelling&#8217;</span></p>
<p>d1 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d2 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span>canceller<span class="br0">&#41;</span><br />
d2.<span class="me1">addErrback</span><span class="br0">&#40;</span>printCancel<span class="br0">&#41;</span><br />
d1.<span class="me1">chainDeferred</span><span class="br0">&#40;</span>d2<span class="br0">&#41;</span><br />
d2.<span class="me1">cancel</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d1.<span class="me1">callback</span><span class="br0">&#40;</span><span class="st0">&#8216;hey&#8217;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p><strong>boom2.py:</strong></p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="co1"># Normally: raises defer.AlreadyCalledError because calling d1.callback</span><br />
<span class="co1"># will call d2, which has already been called.</span></p>
<p><span class="co1"># With tdefer.py: Raises AssertionError: &quot;Can&#8217;t callback an already</span><br />
<span class="co1"># chained deferred&quot; because calling callback on a deferred that&#8217;s</span><br />
<span class="co1"># already been chained is asking for trouble (as above).</span></p>
<p>d1 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d2 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d1.<span class="me1">chainDeferred</span><span class="br0">&#40;</span>d2<span class="br0">&#41;</span><br />
d2.<span class="me1">callback</span><span class="br0">&#40;</span><span class="st0">&#8216;hey&#8217;</span><span class="br0">&#41;</span><br />
d1.<span class="me1">callback</span><span class="br0">&#40;</span><span class="st0">&#8216;jude&#8217;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p><strong>uncalled.py:</strong></p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="co1"># Normally: although d2 has been chained to d1, when d1 is cancelled,</span><br />
<span class="co1"># d2&#8242;s cancel method is never called. Even calling d2.cancel ourselves</span><br />
<span class="co1"># after the call to d1.cancel has no effect, as d2 has already been</span><br />
<span class="co1"># called.</span></p>
<p><span class="co1"># With tdefer: both cancel1 and cancel2 are called when d1.cancel is</span><br />
<span class="co1"># called. The additional final call to d2.cancel correctly has no</span><br />
<span class="co1"># effect as d2 has been called (via d1.cancel).</span></p>
<p><span class="kw1">def</span> cancel1<span class="br0">&#40;</span>d<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;cancel one&#8217;</span></p>
<p><span class="kw1">def</span> cancel2<span class="br0">&#40;</span>d<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;cancel two&#8217;</span></p>
<p><span class="kw1">def</span> reportCancel<span class="br0">&#40;</span>fail, which<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; fail.<span class="me1">trap</span><span class="br0">&#40;</span>defer.<span class="me1">CancelledError</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;cancelled&#8217;</span>, which</p>
<p>d1 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span>cancel1<span class="br0">&#41;</span><br />
d1.<span class="me1">addErrback</span><span class="br0">&#40;</span>reportCancel, <span class="st0">&#8216;one&#8217;</span><span class="br0">&#41;</span><br />
d2 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span>cancel2<span class="br0">&#41;</span><br />
d2.<span class="me1">addErrback</span><span class="br0">&#40;</span>reportCancel, <span class="st0">&#8216;two&#8217;</span><span class="br0">&#41;</span><br />
d1.<span class="me1">chainDeferred</span><span class="br0">&#40;</span>d2<span class="br0">&#41;</span><br />
d1.<span class="me1">cancel</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d2.<span class="me1">cancel</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p><strong>unexpected1.py:</strong></p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="co1"># Normally: prints &quot;called: None&quot;, instead of the probably expected</span><br />
<span class="co1"># &quot;called: hey&quot;</span></p>
<p><span class="co1"># tdefer.py: prints &quot;called: hey&quot;</span></p>
<p><span class="kw1">def</span> called<span class="br0">&#40;</span>result<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;called:&#8217;</span>, result</p>
<p>d1 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d2 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d1.<span class="me1">chainDeferred</span><span class="br0">&#40;</span>d2<span class="br0">&#41;</span><br />
d1.<span class="me1">addCallback</span><span class="br0">&#40;</span>called<span class="br0">&#41;</span><br />
d1.<span class="me1">callback</span><span class="br0">&#40;</span><span class="st0">&#8216;hey&#8217;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p><strong>unexpected2.py:</strong></p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="co1"># Normally: prints</span><br />
<span class="co1"># &nbsp; called 2: hey</span><br />
<span class="co1"># &nbsp; called 3: None</span></p>
<p><span class="co1"># tdefer.py: prints</span><br />
<span class="co1"># &nbsp; called 2: hey</span><br />
<span class="co1"># &nbsp; called 3: hey</span></p>
<p><span class="kw1">def</span> report2<span class="br0">&#40;</span>result<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;called 2:&#8217;</span>, result</p>
<p><span class="kw1">def</span> report3<span class="br0">&#40;</span>result<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;called 3:&#8217;</span>, result</p>
<p>d1 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d2 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">addCallback</span><span class="br0">&#40;</span>report2<span class="br0">&#41;</span><br />
d3 = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">addCallback</span><span class="br0">&#40;</span>report3<span class="br0">&#41;</span><br />
d1.<span class="me1">chainDeferred</span><span class="br0">&#40;</span>d2<span class="br0">&#41;</span><br />
d1.<span class="me1">chainDeferred</span><span class="br0">&#40;</span>d3<span class="br0">&#41;</span><br />
d1.<span class="me1">callback</span><span class="br0">&#40;</span><span class="st0">&#8216;hey&#8217;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>I wont go into detail here as this post is already long enough. Those are 3 classes of behavior arising from chainDeferred being very simplistic.  Comments welcome, of course.  Once again, the runnable code is <a href="http://github.com/fluidinfo/chainDeferredExamples">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2010/08/14/twisteds-deferred-class-chaindeferred-method-is-too-simplistic/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Asynchronous data structures with Twisted Deferreds</title>
		<link>http://blogs.fluidinfo.com/terry/2010/07/23/asynchronous-data-structures-with-twisted-deferreds/</link>
		<comments>http://blogs.fluidinfo.com/terry/2010/07/23/asynchronous-data-structures-with-twisted-deferreds/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 22:55:01 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[me]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=668</guid>
		<description><![CDATA[Earlier this week I gave a talk titled Deferred Gratification (slides) at EuroPython in Birmingham. The title was supposed to hint at how much I love Twisted&#8216;s Deferred class, and that it took me some time to really appreciate it. While thinking about Deferreds in the days before the talk, I think I put my [...]]]></description>
			<content:encoded><![CDATA[<p>Earlier this week I gave a talk titled <a href="http://www.europython.eu/talks/talk_abstracts/index.html#talk36">Deferred Gratification</a> (<a href="http://www.slideshare.net/terrycojones/deferred-gratification">slides</a>) at EuroPython in Birmingham. The title was supposed to hint at how much I love <a href="http://twistedmatrix.com/">Twisted</a>&#8216;s <a href="http://twistedmatrix.com/trac/browser/trunk/twisted/internet/defer.py">Deferred</a> class, and that it took me some time to really appreciate it.</p>
<p>While thinking about Deferreds in the days before the talk, I think I put my finger on one of the reasons I find Deferreds so attractive and elegant. The thought can be neatly summarized: <em>Deferreds let you replace synchronous data structures with elegant asynchronous ones</em>.</p>
<p>There are various ways that people get exposed to thinking about programming in an asynchronous style. The great majority do so via building user interfaces, usually with widget libraries wherein one specifies widgets and layouts, sets up event handlers, and then surrenders control to a main loop that thereafter routes events to handlers. Exposure to asynchronous programming via building UIs is becoming much more common as Javascript programmers build client-side web apps that operate asynchronously with web servers (and the &#8220;A&#8221; in AJAX of course stands for asynchronous). Others become aware of asynchronous programming via writing network code (perhaps using Twisted). Relatively few become aware of asynchronous programming via doing async filesystem I/O.</p>
<p>Because Twisted&#8217;s Deferreds don&#8217;t have anything to do with UIs or networking or filesystems, you can use them to implement other asynchronous things, like an asynchronous data structure. To show you what I mean, here&#8217;s a slightly simplified version of Twisted&#8217;s DeferredQueue class, taken from <a href="http://twistedmatrix.com/trac/browser/trunk/twisted/internet/defer.py">twisted/internet/defer.py</a>:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">class</span> DeferredQueue<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># It would be better if these both used collections.deque (see comments section below).</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">waiting</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="co1"># Deferreds that are expecting an object</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">pending</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span> <span class="co1"># Objects queued to go out via get.</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> put<span class="br0">&#40;</span><span class="kw2">self</span>, obj<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">self</span>.<span class="me1">waiting</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">waiting</span>.<span class="me1">pop</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span>.<span class="me1">callback</span><span class="br0">&#40;</span>obj<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">pending</span>.<span class="me1">append</span><span class="br0">&#40;</span>obj<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> get<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">self</span>.<span class="me1">pending</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> succeed<span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">pending</span>.<span class="me1">pop</span><span class="br0">&#40;</span><span class="nu0">0</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d = Deferred<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">waiting</span>.<span class="me1">append</span><span class="br0">&#40;</span>d<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> d<br />
&nbsp;</div>
<p>I find this extremely elegant, and I&#8217;m going to explain why.</p>
<p>But first, think about code for a regular synchronous queue. What happens if you call get on a regular queue that&#8217;s empty? Almost certainly one of two things: you&#8217;ll get some kind of QueueEmpty error, or else your code will block until some other code puts something into the queue. I.e., you either get a synchronous error or you get a synchronous non-empty response.</p>
<p>If you look at the get method in the code above, you&#8217;ll see that if the queue is empty (i.e., the pending list is empty), a new Deferred is made, added to self.waiting, and is immediately returned to the caller. So code calling get on an empty queue doesn&#8217;t get an error and doesn&#8217;t block, it always gets a result back essentially immediately. How can you get a result from an empty queue? Easy: the result is a Deferred. And because we&#8217;re in the asynchronous world, you just attach callbacks (like event handlers in the UI world) to the Deferred, and go on your merry way.</p>
<p>If you can follow that thinking, the rest of the code in the class above should be easy to grok. In put, if there are any outstanding Deferreds (i.e., earlier callers who hit an empty queue and got a Deferred back), the incoming object is given to the first of these by passing it to the callback function of the Deferred (and popping it out of the waiting list). If there are no outstanding Deferreds expecting a result, the incoming object is simply appended to self.pending. On the get side, if the queue (i.e., self.pending) is non-empty, the code creates a Deferred that has already been fired (using the succeed helper function) and returns it.</p>
<p>By now, this kind of code seems routine and straightforward to me. But it certainly wasn&#8217;t always that way. So if the above seems cryptic or abstract, I encourage you to think it over, maybe write some code, ask questions below, etc. To my mind, these kinds of constructs &#8211; simple, elegant, robust, practical, obviously(?) bug-free, single-threaded, etc. &#8211; are extremely instructive. You too can solve potentially gnarly (at least in the threaded world) networking coding challenges in very simple ways just by building code out of simple Twisted Deferreds (there&#8217;s nothing special about the DeferredQueue class, it&#8217;s just built using primitive Deferreds).</p>
<p>For extra points, think about the concept of asynchronous data structures. I find that concept very attractive, and putting my finger on it helped me to see part of the reason why I think Deferreds are so great. (In fact, as you can see from the use of succeed, Deferreds are <em>not</em> specifically asynchronous or synchronous: they&#8217;re so simple they don&#8217;t even care, and as a consumer of Deferreds, your code doesn&#8217;t have to either). That&#8217;s all remarkably elegant.</p>
<p>I sometimes hope <a href="http://oreilly.com">O&#8217;Reilly</a> will publish a second volume of <a href="http://oreilly.com/catalog/9780596510046">Beautiful Code</a> and ask me to write a chapter. I know exactly what I&#8217;d write about :-) </p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2010/07/23/asynchronous-data-structures-with-twisted-deferreds/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Twisted code for retrying function calls</title>
		<link>http://blogs.fluidinfo.com/terry/2009/11/12/twisted-code-for-retrying-function-calls/</link>
		<comments>http://blogs.fluidinfo.com/terry/2009/11/12/twisted-code-for-retrying-function-calls/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 09:53:05 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=638</guid>
		<description><![CDATA[These days I often find myself writing code to talk to services that are periodically briefly unavailable. An error of some kind occurs and the correct (and documented) action to take is just to retry the original call a little later. Examples include using Amazon&#8217;s S3 service and the Twitter API. In both of these [...]]]></description>
			<content:encoded><![CDATA[<p>These days I often find myself writing code to talk to services that are periodically briefly unavailable. An error of some kind occurs and the correct (and documented) action to take is just to retry the original call a little later.  Examples include using Amazon&#8217;s S3 service and the Twitter API. In both of these services, transient failures happen fairly frequently.</p>
<p>So I wrote the <a href="http://twistedmatrix.com">Twisted</a> class below to retry calls, and tried to make it fairly general. I&#8217;d be happy to hear comments on it, because it&#8217;s pretty simple and if it can be made bullet proof I imagine others will use it too.</p>
<p>In case you&#8217;re not familiar with Twisted and it&#8217;s not clear, the call retrying in the below is scheduled by the Twisted reactor. This all asynchronous event-based code that will not block (assuming the function you pass in also does not).</p>
<p>First off, here&#8217;s the class that handles the calling:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">from</span> twisted.<span class="me1">internet</span> <span class="kw1">import</span> reactor, defer, task<br />
<span class="kw1">from</span> twisted.<span class="me1">python</span> <span class="kw1">import</span> log, failure</p>
<p><span class="kw1">class</span> RetryingCall<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Calls a function repeatedly, passing it args and kw args. Failures<br />
&nbsp; &nbsp; are passed to a user-supplied failure testing function. If the failure<br />
&nbsp; &nbsp; is ignored, the function is called again after a delay whose duration<br />
&nbsp; &nbsp; is obtained from a user-supplied iterator. The start method (below)<br />
&nbsp; &nbsp; returns a deferred that fires with the eventual non-error result of<br />
&nbsp; &nbsp; calling the supplied function, or fires its errback if no successful<br />
&nbsp; &nbsp; result can be obtained before the delay backoff iterator raises<br />
&nbsp; &nbsp; StopIteration.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, f, *args, **kw<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._f = f<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._args = args<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._kw = kw<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">def</span> _err<span class="br0">&#40;</span><span class="kw2">self</span>, fail<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">self</span>.<span class="me1">failure</span> <span class="kw1">is</span> <span class="kw2">None</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">failure</span> = fail<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fail = <span class="kw2">self</span>._failureTester<span class="br0">&#40;</span>fail<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._deferred.<span class="me1">errback</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">isinstance</span><span class="br0">&#40;</span>fail, failure.<span class="me1">Failure</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._deferred.<span class="me1">errback</span><span class="br0">&#40;</span>fail<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.<span class="me1">msg</span><span class="br0">&#40;</span><span class="st0">&#8216;RetryingCall: Ignoring %r&#8217;</span> % <span class="br0">&#40;</span>fail,<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._call<span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> _call<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delay = <span class="kw2">self</span>._backoffIterator.<span class="me1">next</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">StopIteration</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.<span class="me1">msg</span><span class="br0">&#40;</span><span class="st0">&#8216;StopIteration in RetryingCall: ran out of attempts.&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._deferred.<span class="me1">errback</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">failure</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d = task.<span class="me1">deferLater</span><span class="br0">&#40;</span>reactor, delay,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._f, *<span class="kw2">self</span>._args, **<span class="kw2">self</span>._kw<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">addCallbacks</span><span class="br0">&#40;</span><span class="kw2">self</span>._deferred.<span class="me1">callback</span>, <span class="kw2">self</span>._err<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> start<span class="br0">&#40;</span><span class="kw2">self</span>, backoffIterator=<span class="kw2">None</span>, failureTester=<span class="kw2">None</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._backoffIterator = <span class="kw2">iter</span><span class="br0">&#40;</span>backoffIterator <span class="kw1">or</span> simpleBackoffIterator<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._failureTester = failureTester <span class="kw1">or</span> <span class="br0">&#40;</span><span class="kw1">lambda</span> _: <span class="kw2">None</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._deferred = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">failure</span> = <span class="kw2">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>._call<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>._deferred<br />
&nbsp;</div>
<p>You call the constructor with your function and the args it should be called with. Then you call start() to get back a deferred that will eventually fire with the result of the call, or an error. BTW, I called it &#8220;start&#8221; to mirror <tt>twisted.internet.task.LoopingCall</tt>.</p>
<p>There&#8217;s a helper function for producing successive inter-call delays:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">from</span> <span class="kw3">operator</span> <span class="kw1">import</span> mul<br />
<span class="kw1">from</span> functools <span class="kw1">import</span> partial</p>
<p><span class="kw1">def</span> simpleBackoffIterator<span class="br0">&#40;</span>maxResults=<span class="nu0">10</span>, maxDelay=<span class="nu0">120.0</span>, now=<span class="kw2">True</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; initDelay=<span class="nu0">0.01</span>, incFunc=<span class="kw2">None</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">assert</span> maxResults &gt; <span class="nu0">0</span><br />
&nbsp; &nbsp; remaining = maxResults<br />
&nbsp; &nbsp; delay = initDelay<br />
&nbsp; &nbsp; incFunc = incFunc <span class="kw1">or</span> partial<span class="br0">&#40;</span>mul, <span class="nu0">2.0</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">if</span> now:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">yield</span> <span class="nu0">0.0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; remaining -= <span class="nu0">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">while</span> remaining &gt; <span class="nu0">0</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">yield</span> <span class="br0">&#40;</span>delay <span class="kw1">if</span> delay &lt; maxDelay <span class="kw1">else</span> maxDelay<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; delay = incFunc<span class="br0">&#40;</span>delay<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; remaining -= <span class="nu0">1</span><br />
&nbsp;</div>
<p>By default this will generate the sequence of inter-call delays 0.0, 0.01, 0.02, 0.04, 0.08, 0.16, 0.32, 0.64, 1.28, 2.56 and it should be easy to see how you could write your own. Or you can just supply a list, etc.  When the backoff iterator finishes, the RetryingCall class gives up on trying to get a non-error result from the function. In that case errback is called on the deferred that start() returns, with the failure from the first call.</p>
<p>You get to specify a function for testing failures. If it ever raises or returns a failure, the start() deferred&#8217;s errback is called. The failure tester can just ignore whatever failures should be considered transient.</p>
<p>So, for example, if you were calling S3 and wanted to ignore 504 errors, you could supply a failureTester arg like this:</p>
<div class="dean_ch" style="white-space: nowrap;">
&nbsp; &nbsp; <span class="kw1">from</span> twisted.<span class="me1">web</span> <span class="kw1">import</span> error, http</p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw3">test</span><span class="br0">&#40;</span><span class="kw2">self</span>, failure<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; failure.<span class="me1">trap</span><span class="br0">&#40;</span>error.<span class="me1">Error</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">int</span><span class="br0">&#40;</span>failure.<span class="me1">value</span>.<span class="me1">status</span><span class="br0">&#41;</span> != http.<span class="me1">GATEWAY_TIMEOUT</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> failure<br />
&nbsp;</div>
<p>As another example, while using the Twitter API you might want to allow a range of HTTP errors and also exactly one 404 error, seeing as a 404 <em>might</em> be an error on the part of Twitter (I don&#8217;t mean to suggest that actually happens). It&#8217;s probably definitive &#8211; but, why not try it once again just to be more sure?  So, pass RetryingCall a failureTester that&#8217;s an instance of a class like this:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">class</span> TwitterFailureTester<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; okErrs = <span class="br0">&#40;</span>http.<span class="me1">INTERNAL_SERVER_ERROR</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.<span class="me1">BAD_GATEWAY</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.<span class="me1">SERVICE_UNAVAILABLE</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">seen404</span> = <span class="kw2">False</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__call__</span><span class="br0">&#40;</span><span class="kw2">self</span>, failure<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; failure.<span class="me1">trap</span><span class="br0">&#40;</span>error.<span class="me1">Error</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; status = <span class="kw2">int</span><span class="br0">&#40;</span>failure.<span class="me1">value</span>.<span class="me1">status</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> status == http.<span class="me1">NOT_FOUND</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">self</span>.<span class="me1">seen404</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> failure<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">seen404</span> = <span class="kw2">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> status <span class="kw1">not</span> <span class="kw1">in</span> <span class="kw2">self</span>.<span class="me1">okErrs</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> failure<br />
&nbsp;</div>
<p>Changing existing code to use RetryingCall is pretty trivial. Take something like this</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">from</span> twisted.<span class="me1">web</span> <span class="kw1">import</span> client</p>
<p><span class="kw1">def</span> getUserByScreenname<span class="br0">&#40;</span>screenname<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; d = client.<span class="me1">getPage</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;http://twitter.com/users/show.json?screen_name=glyf&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> d<br />
&nbsp;</div>
<p>and change it to look like this:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">def</span> getUserByScreenname<span class="br0">&#40;</span>screenname<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; r = RetryingCall<span class="br0">&#40;</span>client.<span class="me1">getPage</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;http://twitter.com/users/show.json?screen_name=glyf&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d = r.<span class="me1">start</span><span class="br0">&#40;</span>failureTester=TwitterFailureTester<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> d<br />
&nbsp;</div>
<p>I wrote this about 10 days ago and posted it to the Twisted mailing list. No-one replied to say how horrible the code is or that it shoud be done another way, which is a pretty good sign. The above includes <a href="http://twistedmatrix.com/pipermail/twisted-python/2009-November/020822.html">an improvement suggested by Tim Allen</a>, and is slightly more useful than the code I posted originally (see <a href="http://twistedmatrix.com/pipermail/twisted-python/2009-November/020818.html">the thread on the Twisted list</a> for details).</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2009/11/12/twisted-code-for-retrying-function-calls/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Fault-tolerant Python Twisted classes for getting all Twitter friends or followers</title>
		<link>http://blogs.fluidinfo.com/terry/2009/10/22/fault-tolerant-python-twisted-classes-for-getting-all-twitter-friends-or-followers/</link>
		<comments>http://blogs.fluidinfo.com/terry/2009/10/22/fault-tolerant-python-twisted-classes-for-getting-all-twitter-friends-or-followers/#comments</comments>
		<pubDate>Wed, 21 Oct 2009 23:56:20 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=634</guid>
		<description><![CDATA[It&#8217;s been forever since I blogged here. I just wrote a little Python to grab all of a user&#8217;s friends or followers (or just their user ids). It uses Twisted, of course. There were two main reasons for doing this: 1) I want all friends/followers, not just the first bunch returned by the Twitter API, [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s been forever since I blogged here. I just wrote a little Python to grab all of a user&#8217;s friends or followers (or just their user ids). It uses <a href="http://twistedmatrix.com">Twisted</a>, of course. There were two main reasons for doing this: 1) I want <em>all</em> friends/followers, not just the first bunch returned by the <a href="http://apiwiki.twitter.com/">Twitter API</a>, and 2) I wanted code that is fairly robust in the face of various 50x HTTP errors (I regularly experience INTERNAL_SERVER_ERROR, BAD_GATEWAY, and SERVICE_UNAVAILABLE).</p>
<p>If you want to use the code below and you&#8217;re not familiar with the Twitter API, consider whether you can use the <code>FriendsIdFetcher</code> and <code>FollowersIdFetcher</code> classes as they&#8217;ll do far fewer requests (you get 5000 results per API call, instead of 100). If you can live with user ids and do the occasional fetch of a full user, you&#8217;ll probably do far fewer API calls.</p>
<p>For the <code>FriendsFetcher</code> and <code>FollowersFetcher</code> classes, you get back a list of dictionaries, one per user. For <code>FriendsIdFetcher</code> and <code>FollowersIdFetcher</code> you get a list of Twitter user ids.</p>
<p><em>Of course</em> there&#8217;s no documentation. Feel free to ask questions in the comments. <a href="http://jon.es/other/twitter-fetcher.py">Download the source</a>.</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">import</span> <span class="kw3">sys</span></p>
<p><span class="kw1">from</span> twisted.<span class="me1">internet</span> <span class="kw1">import</span> defer<br />
<span class="kw1">from</span> twisted.<span class="me1">web</span> <span class="kw1">import</span> client, error, http<br />
&nbsp; &nbsp; <br />
<span class="kw1">if</span> <span class="kw3">sys</span>.<span class="me1">hexversion</span> &gt;= 0x20600f0:<br />
&nbsp; &nbsp; <span class="kw1">import</span> json<br />
<span class="kw1">else</span>:<br />
&nbsp; &nbsp; <span class="kw1">import</span> simplejson as json</p>
<p><span class="kw1">class</span> _Fetcher<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; baseURL = <span class="st0">&#8216;http://twitter.com/&#8217;</span><br />
&nbsp; &nbsp; URITemplate = <span class="kw2">None</span> <span class="co1"># Override in subclass.</span><br />
&nbsp; &nbsp; dataKey = <span class="kw2">None</span> <span class="co1"># Override in subclass.</span><br />
&nbsp; &nbsp; maxErrs = <span class="nu0">10</span><br />
&nbsp; &nbsp; okErrs = <span class="br0">&#40;</span>http.<span class="me1">INTERNAL_SERVER_ERROR</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.<span class="me1">BAD_GATEWAY</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.<span class="me1">SERVICE_UNAVAILABLE</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, name<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">assert</span> <span class="kw2">self</span>.<span class="me1">baseURL</span>.<span class="me1">endswith</span><span class="br0">&#40;</span><span class="st0">&#8216;/&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">results</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">errCount</span> = <span class="nu0">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">nextCursor</span> = <span class="nu0">-1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">deferred</span> = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">URL</span> = <span class="kw2">self</span>.<span class="me1">baseURL</span> + <span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">URITemplate</span> % <span class="br0">&#123;</span> <span class="st0">&#8216;name&#8217;</span> : name <span class="br0">&#125;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> _fail<span class="br0">&#40;</span><span class="kw2">self</span>, failure<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; failure.<span class="me1">trap</span><span class="br0">&#40;</span>error.<span class="me1">Error</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">errCount</span> += <span class="nu0">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">errCount</span> &lt; <span class="kw2">self</span>.<span class="me1">maxErrs</span> <span class="kw1">and</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">int</span><span class="br0">&#40;</span>failure.<span class="me1">value</span>.<span class="me1">status</span><span class="br0">&#41;</span> <span class="kw1">in</span> <span class="kw2">self</span>.<span class="me1">okErrs</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">fetch</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">deferred</span>.<span class="me1">errback</span><span class="br0">&#40;</span>failure<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">def</span> _parse<span class="br0">&#40;</span><span class="kw2">self</span>, result<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data = json.<span class="me1">loads</span><span class="br0">&#40;</span>result<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">nextCursor</span> = data.<span class="me1">get</span><span class="br0">&#40;</span><span class="st0">&#8216;next_cursor&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">results</span>.<span class="me1">extend</span><span class="br0">&#40;</span>data<span class="br0">&#91;</span><span class="kw2">self</span>.<span class="me1">dataKey</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">Exception</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">deferred</span>.<span class="me1">errback</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">fetch</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">def</span> _deDup<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">raise</span> <span class="kw2">NotImplementedError</span><span class="br0">&#40;</span><span class="st0">&#8216;Override _deDup in subclasses.&#8217;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> fetch<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">self</span>.<span class="me1">nextCursor</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d = client.<span class="me1">getPage</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">URL</span> + <span class="st0">&#8216;?cursor=%s&#8217;</span> % <span class="kw2">self</span>.<span class="me1">nextCursor</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">addCallback</span><span class="br0">&#40;</span><span class="kw2">self</span>._parse<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">addErrback</span><span class="br0">&#40;</span><span class="kw2">self</span>._fail<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">deferred</span>.<span class="me1">callback</span><span class="br0">&#40;</span><span class="kw2">self</span>._deDup<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">deferred</span></p>
<p><span class="kw1">class</span> _FriendsOrFollowersFetcher<span class="br0">&#40;</span>_Fetcher<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; dataKey = u<span class="st0">&#8216;users&#8217;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">def</span> _deDup<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; seen = <span class="kw2">set</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; result = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> userdict <span class="kw1">in</span> <span class="kw2">self</span>.<span class="me1">results</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uid = userdict<span class="br0">&#91;</span><span class="st0">&#8216;id&#8217;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> uid <span class="kw1">not</span> <span class="kw1">in</span> seen:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.<span class="me1">append</span><span class="br0">&#40;</span>userdict<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; seen.<span class="me1">add</span><span class="br0">&#40;</span>uid<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> result</p>
<p><span class="kw1">class</span> _IdFetcher<span class="br0">&#40;</span>_Fetcher<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; dataKey = u<span class="st0">&#8216;ids&#8217;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span class="kw1">def</span> _deDup<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Keep the ids in the order we received them.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; seen = <span class="kw2">set</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; result = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> uid <span class="kw1">in</span> <span class="kw2">self</span>.<span class="me1">results</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> uid <span class="kw1">not</span> <span class="kw1">in</span> seen:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result.<span class="me1">append</span><span class="br0">&#40;</span>uid<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; seen.<span class="me1">add</span><span class="br0">&#40;</span>uid<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> result</p>
<p><span class="kw1">class</span> FriendsFetcher<span class="br0">&#40;</span>_FriendsOrFollowersFetcher<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; URITemplate = <span class="st0">&#8216;statuses/friends/%(name)s.json&#8217;</span></p>
<p><span class="kw1">class</span> FollowersFetcher<span class="br0">&#40;</span>_FriendsOrFollowersFetcher<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; URITemplate = <span class="st0">&#8216;statuses/followers/%(name)s.json&#8217;</span></p>
<p><span class="kw1">class</span> FriendsIdFetcher<span class="br0">&#40;</span>_IdFetcher<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; URITemplate = <span class="st0">&#8216;friends/ids/%(name)s.json&#8217;</span></p>
<p><span class="kw1">class</span> FollowersIdFetcher<span class="br0">&#40;</span>_IdFetcher<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; URITemplate = <span class="st0">&#8216;followers/ids/%(name)s.json&#8217;</span><br />
&nbsp;</div>
<p>Usage is dead simple:</p>
<div class="dean_ch" style="white-space: nowrap;">
fetcher = FriendsFetcher<span class="br0">&#40;</span><span class="st0">&#8216;terrycojones&#8217;</span><span class="br0">&#41;</span><br />
d = fetcher.<span class="me1">fetch</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d.<span class="me1">addCallback</span><span class="br0">&#40;</span>&#8230;.<span class="br0">&#41;</span> <span class="co1"># etc.</span><br />
&nbsp;</div>
<p>Enjoy.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2009/10/22/fault-tolerant-python-twisted-classes-for-getting-all-twitter-friends-or-followers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Facebook release Tornado and it&#8217;s not based on Twisted?</title>
		<link>http://blogs.fluidinfo.com/terry/2009/09/12/facebook-release-tornado-and-its-not-based-on-twisted/</link>
		<comments>http://blogs.fluidinfo.com/terry/2009/09/12/facebook-release-tornado-and-its-not-based-on-twisted/#comments</comments>
		<pubDate>Sat, 12 Sep 2009 13:25:22 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[FluidDB]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=614</guid>
		<description><![CDATA[To their great credit, Facebook have just open-sourced more of their core software. This time it&#8217;s Tornado, an asynchronous web server written in Python. Surely that can only mean one thing: Tornado is based on Twisted. Right? Incredibly, no. Words fail me on this one. I&#8217;ve spent some hours today trying to put my thoughts [...]]]></description>
			<content:encoded><![CDATA[<p><div id="attachment_613" class="wp-caption alignleft" style="width: 170px"><a href="http://www.flickr.com/photos/photogeny/437405458/"><img src="http://blogs.fluidinfo.com/terry/wp-content/uploads/2009/09/tornado.jpg" alt="Image: Jay Smith" title="tornado" width="160" height="240" class="size-full wp-image-613" /></a><p class="wp-caption-text">Image: Jay Smith</p></div> To their great credit, Facebook have just open-sourced more of their core software. This time it&#8217;s <a href="http://www.tornadoweb.org/">Tornado</a>, an asynchronous web server written in <a href="http://python.org">Python</a>.</p>
<p>Surely that can only mean one thing: Tornado is based on <a href="http://twistedmatrix.com">Twisted</a>. Right?</p>
<p>Incredibly, no. Words fail me on this one. I&#8217;ve spent some hours today trying to put my thoughts into order so I could put together a reasonably coherent blog post on the subject. But I&#8217;ve failed. So here are some unstructured thoughts.</p>
<p>First of all, I&#8217;m not meaning to bash Facebook on this. At <a href="http://fluidinfo.com">Fluidinfo</a> we use their <a href="http://incubator.apache.org/thrift/">Thrift</a> code. We&#8217;ll almost certainly use <a href="http://developers.facebook.com/scribe/">Scribe</a> for logging at some point, and we&#8217;re seriously considering using <a href="http://incubator.apache.org/cassandra/">Cassandra</a>. <a href="http://twitter.com/esteve">Esteve Fernandez</a> has put a ton of work into <a href="https://launchpad.net/txamqp">txAMQP</a> to glue together Thrift, Twisted, and <a href="http://amqp.org">AMQP</a>, and in the process became a Thrift committer.</p>
<p>Second, you can understand&#8212;or make an educated guess at&#8212;what happened: the Facebook programmers, like programmers everywhere, were strongly tempted to just write their own code instead of dealing with someone else&#8217;s. It&#8217;s not just about learning curves and fixing deficiencies, there are also issues of speed of changes and of control. At Fluidinfo we suffered through six months of maintaining our own set of related patches to Thrift before the Twisted support Esteve wrote was finally merged to trunk. That was painful and the temptation to scratch our own itch, fork, and forget about the official Thrift project was high.</p>
<p>Plus, Twisted suffers from the fact that the documentation is not as good as it could be. <a href="http://www.twistedmatrix.com/pipermail/twisted-web/2006-July/002748.html">I commented at length on this</a> over three years ago. Please read the follow-up posts in that thread for an illustration (one of many) of the maturity of the people running Twisted. Also note that the documentation has improved greatly since then. Nevertheless, Twisted is a huge project, it has tons of parts, and it&#8217;s difficult to document and to wrap your head around no matter what.</p>
<p>So you can understand why Facebook might have decided not to use Twisted. <a href="http://bret.appspot.com/entry/tornado-web-server">In their words</a>:</p>
<blockquote><p>We ended up writing our own web server and framework after looking at existing servers and tools like Twisted because none matched both our performance requirements and our ease-of-use requirements.</p></blockquote>
<p>I&#8217;m betting it&#8217;s that last part that&#8217;s the key to the decision not to use Twisted.</p>
<p>But seriously&#8230;&#8230; WTF?</p>
<p>Twisted is an amazing piece of work, written by some truly brilliant coders, with huge experience doing <em>exactly</em> what Facebook set out to reinvent.</p>
<p>This is where I&#8217;m at a loss for words. I think: &#8220;what an historic missed opportunity&#8221; and &#8220;reinventing the wheel, badly&#8221; and &#8220;no, no, no, this cannot be&#8221; and &#8220;this is just so short-sighted&#8221; and &#8220;a crying shame&#8221; and many things besides. </p>
<p>Sure, Twisted is difficult to grok. But that&#8217;s no excuse. It&#8217;s a seriously cool and powerful framework, it&#8217;s vastly more sophisticated and useful and extensible than what Facebook have cobbled together. Facebook could have worked to improve twisted.web (which everyone agrees has some shortcomings) which could have benefitted greatly from even a small fraction of the resources Facebook must have put into Tornado. The end result would have been much better. Or Facebook could have just ignored twisted.web and built directly on top of the Twisted core. That would have been great too.</p>
<p>Or Facebook could have had a team of people who knew how to do it better, and produced something better than Twisted. I guess that&#8217;s the real frustration here &#8211; they&#8217;ve put a ton of effort into building something much more limited in scope and vision, and even the piece that they did build looks like a total hack built to scratch their short term needs.</p>
<p>What&#8217;s the biggest change in software engineering over the last decade? Arguably it&#8217;s the rise of <a href="http://en.wikipedia.org/wiki/Test-driven_development">test-driven development</a>. <a href="http://www.tbray.org/ongoing/When/200x/2009/06/23/TDD-Heresy">I&#8217;m not the only one who thinks so</a>. Yet here we are in late 2009 and Facebook have released a major piece of code with no test suite. Amazing. OK, you could argue this is a minor thing, that it&#8217;s not core to Tornado. That argument has some weight, but it&#8217;s hard to think that this thing is not a hack.</p>
<p>If you decide to use an asynchronous web framework, do you expect to have to <a href="http://github.com/facebook/tornado/blob/9e24ae162d024e4049b8811d7ca19e319c20021d/tornado/httpserver.py#L84">manually set your sockets to be non-blocking</a>? Do you feel like <a href="http://github.com/facebook/tornado/blob/9e24ae162d024e4049b8811d7ca19e319c20021d/tornado/ioloop.py#L47">catching  EWOULDBLOCK and EAGAIN yourself</a>? Those sorts of things, and their non-portability (even within the world of Linux) are precisely the kinds of things that lead people away from writing C and towards doing rapid development using something robust and portable that looks after the details. They&#8217;re precisely the things Twisted takes care of for you, and which (at least in Twisted) work across platforms, including Windows.</p>
<p>It looks like Tornado are <a href="http://github.com/facebook/tornado/blob/9e24ae162d024e4049b8811d7ca19e319c20021d/tornado/ioloop.py#L100-">using a global reactor</a>, which the Twisted folks have learned the hard way is not the best solution.</p>
<p>Those are just some of the complaints I&#8217;ve heard and seen in the Tornado code. I confess I&#8217;ve looked only superficially at their code &#8211; but more than enough to feel such a sense of lost opportunity. They built a small subsection of Twisted, they&#8217;ve done it with much less experience and elegance and hiding of detail than the Twisted code, and the thing doesn&#8217;t even come with a test suite. Who knows if it actually works, or when, or where, etc.?</p>
<p>And&#8230;. Twisted is <em>so much more</em>. HTTP is just one of many protocols Twisted speaks, including (from <a href="http://twistedmatrix.com">their home page</a>): &#8220;TCP, UDP, SSL/TLS, multicast, Unix sockets, a large number of protocols including HTTP, NNTP, IMAP, SSH, IRC, FTP, and others&#8221;.</p>
<p>Want to build a sophisticated, powerful, and flexible asynchronous internet service in Python? <strong>Use Twisted.</strong></p>
<p>A beautiful thing about Twisted is that it expands your mind. Its abstractions (particularly the clean separation and generality of transports, protocols, factories, services, and Deferreds&#8212;see <a href="http://twistedmatrix.com/projects/core/documentation/howto/defer.html">here</a> and <a href="http://twistedmatrix.com/projects/core/documentation/howto/gendefer.html">here</a> and <a href="http://twistedmatrix.com/projects/core/documentation/howto/deferredindepth.html">here</a>) makes you a better programmer. As I wrote to some friends in April 2006: &#8220;Reading the Twisted docs makes me feel like my brain is growing new muscles.&#8221;</p>
<p>Twisted&#8217;s deferreds are extraordinarily elegant and powerful, I&#8217;ve blogged and posted to the Twisted mailing list about them on multiple occasions. Learning to think in the Twisted way has been a programming joy to me over the last 3 years, so you can perhaps imagine my dismay that a company with the resources of Facebook couldn&#8217;t be bothered to get behind it and had to go reinvent the wheel, and do it so poorly. What a pity.</p>
<p>In my case, <em>I threw away an entire year of C code in order to use Twisted</em> in <a href="http://doc.fluidinfo.com/fluidDB">FluidDB</a>. That was a decision I didn&#8217;t take lightly. I&#8217;d written my own libraries to do lots of low level network communications and RPC &#8211; including auto-generating server and client side glue libraries to serialize and unserialize RPC calls and args (a bit like Thrift), plus a server and tons of other stuff. I chucked it because it was too brittle. It was too much of a hack. It wasn&#8217;t portable enough. It was too get the details right. It wasn&#8217;t extensible.</p>
<p>In other words&#8230;.. <em>it was too much like Tornado!</em> So I threw it all away in favor of Twisted. As I happily tell people, FluidDB is written in Python so it can use Twisted. It was a question of an amazingly great asynchronous networking framework determining the choice of programming language. And this was done in spite of the fact that I thought the Twisted docs sucked badly. The people behind Twisted were clearly brilliant and the community was great. There was an opportunity to make a bet on something and to contribute. I wish Facebook had made the same decision. It&#8217;s everyone&#8217;s loss that they did not. What a great pity.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2009/09/12/facebook-release-tornado-and-its-not-based-on-twisted/feed/</wfw:commentRss>
		<slash:comments>17</slash:comments>
		</item>
		<item>
		<title>A mixin class allowing Python __init__ methods to work with Twisted deferreds</title>
		<link>http://blogs.fluidinfo.com/terry/2009/05/11/a-mixin-class-allowing-python-__init__-methods-to-work-with-twisted-deferreds/</link>
		<comments>http://blogs.fluidinfo.com/terry/2009/05/11/a-mixin-class-allowing-python-__init__-methods-to-work-with-twisted-deferreds/#comments</comments>
		<pubDate>Mon, 11 May 2009 16:54:51 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>
		<category><![CDATA[Deferred]]></category>
		<category><![CDATA[Twisted]]></category>
		<category><![CDATA[__init__]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=579</guid>
		<description><![CDATA[I posted to the Python Twisted list back in Nov 2008 with subject: A Python metaclass for Twisted allowing __init__ to return a Deferred Briefly, I was trying to find a nice way to allow the __init__ method of a class to work with deferreds in such a way that methods of the class could [...]]]></description>
			<content:encoded><![CDATA[<p>I posted to <a href="http://twistedmatrix.com/pipermail/twisted-python/">the Python Twisted list</a> back in Nov 2008 with subject: A Python metaclass for <a href="http://twistedmatrix.com/">Twisted</a> allowing <code>__init__</code> to return a Deferred</p>
<p>Briefly, I was trying to find a nice way to allow the <code>__init__</code> method of a class to work with deferreds in such a way that methods of the class could use work done by <code>__init__</code> safe in the knowledge that the deferreds had completed.  E.g., if you have</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">class</span> X<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, host, port<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> final<span class="br0">&#40;</span>connection<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">db</span> = connection<br />
&nbsp; &nbsp; &nbsp; &nbsp; d = makeDBConnection<span class="br0">&#40;</span>host, port<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">addCallback</span><span class="br0">&#40;</span>final<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> query<span class="br0">&#40;</span><span class="kw2">self</span>, q<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">db</span>.<span class="me1">runQuery</span><span class="br0">&#40;</span>q<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Then when you make an X and call query on it, there&#8217;s a chance the deferred wont have fired, and you&#8217;ll get an error.  This is just a very simple illustrative example.  There are many more, and this is a general problem of the synchronous world (in which <code>__init__</code> is supposed to prepare a fully-fledged class instance and cannot return a deferred) meeting the asynchronous world in which, as Twisted programmers, we would like to (and must) use deferreds.</p>
<p>The earlier thread, with lots of useful followups <a href="http://twistedmatrix.com/pipermail/twisted-python/2008-November/018600.html">can be read here</a>. Although I learned a lot in that thread, I wasn&#8217;t completely happy with any of the solutions. Some of the things that still bugged me are in posts towards the end of the thread (<a href="http://twistedmatrix.com/pipermail/twisted-python/2008-November/018624.html">here</a> and <a href="http://twistedmatrix.com/pipermail/twisted-python/2008-November/018634.html">here</a>).</p>
<p>The various approaches we took back then all boiled down to waiting for a deferred to fire before the class instance was fully ready to use. When that happened, you had your instance and could call its methods.</p>
<p>I had also thought about an alternate approach: having <code>__init__</code> add a callback to the deferreds it dealt with to set a flag in self and then have all dependent methods check that flag to see if the class instance was ready for use. But that 1) is ugly (too much extra code); 2) means the caller has to be prepared to deal with errors due to the class instance not being ready, and 3) adds a check to every method call. It would look something like this:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">class</span> X<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, host, port<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ready</span> = <span class="kw2">False</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> final<span class="br0">&#40;</span>connection<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">db</span> = connection<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ready</span> = <span class="kw2">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; d = makeDBConnection<span class="br0">&#40;</span>host, port<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">addCallback</span><span class="br0">&#40;</span>final<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> query<span class="br0">&#40;</span><span class="kw2">self</span>, q<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> <span class="kw2">self</span>.<span class="me1">ready</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">raise</span> IAmNotReadyException<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span>.<span class="me1">db</span>.<span class="me1">runQuery</span><span class="br0">&#40;</span>q<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>That was too ugly for my taste, for all of the above reasons, most especially for forcing the unfortunate caller of my code to handle <code>IAmNotReadyException</code>.</p>
<p>Anyway&#8230;. fast forward 6 months and I&#8217;ve hit the same problem again. It&#8217;s with existing code, in which I would like an <code>__init__</code> to call something that (now, due to changes elsewhere) returns a deferred. So I started thinking again, and came up with a much cleaner way to do the alternate approach via a class mixin:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">from</span> twisted.<span class="me1">internet</span> <span class="kw1">import</span> defer</p>
<p><span class="kw1">class</span> deferredInitMixin<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> wrap<span class="br0">&#40;</span><span class="kw2">self</span>, d, *wrappedMethods<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">waiting</span> = <span class="br0">&#91;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">stored</span> = <span class="br0">&#123;</span><span class="br0">&#125;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> restore<span class="br0">&#40;</span>_<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> method <span class="kw1">in</span> <span class="kw2">self</span>.<span class="me1">stored</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">setattr</span><span class="br0">&#40;</span><span class="kw2">self</span>, method, <span class="kw2">self</span>.<span class="me1">stored</span><span class="br0">&#91;</span>method<span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> d <span class="kw1">in</span> <span class="kw2">self</span>.<span class="me1">waiting</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">callback</span><span class="br0">&#40;</span><span class="kw2">None</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> makeWrapper<span class="br0">&#40;</span>method<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> wrapper<span class="br0">&#40;</span>*args, **kw<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">addCallback</span><span class="br0">&#40;</span><span class="kw1">lambda</span> _: <span class="kw2">self</span>.<span class="me1">stored</span><span class="br0">&#91;</span>method<span class="br0">&#93;</span><span class="br0">&#40;</span>*args, **kw<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">waiting</span>.<span class="me1">append</span><span class="br0">&#40;</span>d<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> d<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> wrapper</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> method <span class="kw1">in</span> wrappedMethods:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">stored</span><span class="br0">&#91;</span>method<span class="br0">&#93;</span> = <span class="kw2">getattr</span><span class="br0">&#40;</span><span class="kw2">self</span>, method<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">setattr</span><span class="br0">&#40;</span><span class="kw2">self</span>, method, makeWrapper<span class="br0">&#40;</span>method<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; d.<span class="me1">addCallback</span><span class="br0">&#40;</span>restore<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>You use it as in the class Test below:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">from</span> twisted.<span class="me1">internet</span> <span class="kw1">import</span> defer, reactor</p>
<p><span class="kw1">def</span> fire<span class="br0">&#40;</span>d, value<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;I finally fired, with value&quot;</span>, value<br />
&nbsp; &nbsp; d.<span class="me1">callback</span><span class="br0">&#40;</span>value<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> late<span class="br0">&#40;</span>value<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; d = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; reactor.<span class="me1">callLater</span><span class="br0">&#40;</span><span class="nu0">1</span>, fire, d, value<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> d</p>
<p><span class="kw1">def</span> called<span class="br0">&#40;</span>result, what<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;final callback of %s, result = %s&#8217;</span> % <span class="br0">&#40;</span>what, result<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> stop<span class="br0">&#40;</span>_<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; reactor.<span class="me1">stop</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>
<span class="kw1">class</span> Test<span class="br0">&#40;</span>deferredInitMixin<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; d = late<span class="br0">&#40;</span><span class="st0">&#8216;Test&#8217;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; deferredInitMixin.<span class="me1">wrap</span><span class="br0">&#40;</span><span class="kw2">self</span>, d, <span class="st0">&#8216;f1&#8242;</span>, <span class="st0">&#8216;f2&#8242;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> f1<span class="br0">&#40;</span><span class="kw2">self</span>, arg<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;f1 called with&quot;</span>, arg<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> late<span class="br0">&#40;</span>arg<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> f2<span class="br0">&#40;</span><span class="kw2">self</span>, arg<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&quot;f2 called with&quot;</span>, arg<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> late<span class="br0">&#40;</span>arg<span class="br0">&#41;</span></p>
<p>
<span class="kw1">if</span> __name__ == <span class="st0">&#8216;__main__&#8217;</span>:<br />
&nbsp; &nbsp; t = Test<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d1 = t.<span class="me1">f1</span><span class="br0">&#40;</span><span class="nu0">44</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d1.<span class="me1">addCallback</span><span class="br0">&#40;</span>called, <span class="st0">&#8216;f1&#8242;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d2 = t.<span class="me1">f1</span><span class="br0">&#40;</span><span class="nu0">33</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d2.<span class="me1">addCallback</span><span class="br0">&#40;</span>called, <span class="st0">&#8216;f1&#8242;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d3 = t.<span class="me1">f2</span><span class="br0">&#40;</span><span class="nu0">11</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d3.<span class="me1">addCallback</span><span class="br0">&#40;</span>called, <span class="st0">&#8216;f2&#8242;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d = defer.<span class="me1">DeferredList</span><span class="br0">&#40;</span><span class="br0">&#91;</span>d1, d2, d3<span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d.<span class="me1">addBoth</span><span class="br0">&#40;</span>stop<span class="br0">&#41;</span><br />
&nbsp; &nbsp; reactor.<span class="me1">run</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Effectively, the <code>__init__</code> of my Test class asks <code>deferredInitMixin</code> to temporarily wrap some of its methods. <code>deferredInitMixin</code> stores the original methods away and replaces each of them with a function that immediately returns a deferred.  So after <code>__init__</code> finishes, code that calls the now-wrapped methods of the class instance before the deferred has fired will get a deferred back as usual (but see * below). As far as they know, everything is normal.  Behind the scenes, <code>deferredInitMixin</code> has arranged for these deferreds to fire only after the deferred passed from <code>__init__</code> has fired.  Once that happens, <code>deferredInitMixin</code> also restores the original functions to the instance. As a result there is no overhead later to check a flag to see if the instance is ready to use. If the deferred from <code>__init__</code> happens to fire before any of the instance&#8217;s methods are called, it will simply restore the original methods.  Finally (obviously?) you only pass the method names to <code>deferredInitMixin</code> that depend on the deferred in <code>__init__</code> being done.</p>
<p>BTW, calling the methods passed to <code>deferredInitMixin</code> &#8220;wrapped&#8221; isn&#8217;t really accurate. They&#8217;re just temporarily replaced.</p>
<p>I quite like this approach.  It&#8217;s a second example of something I posted about <a href="http://twistedmatrix.com/pipermail/twisted-python/2009-April/019522.html">here</a>, in which a pool of deferreds is accumulated and all fired when another deferred fires. It&#8217;s nice because you don&#8217;t reply with an error and there&#8217;s no need for locking or other form of coordination &#8211; the work you need done is already in progress, so you get back a fresh deferred and everything goes swimmingly.</p>
<p>* Minor note: the methods you wrap should probably be ones that already return deferreds. That way you always get a deferred back from them, whether they&#8217;re temporarily wrapped or not. The above mixin works just fine if you ask it to wrap non-deferred-returning functions, but you have to deal with the possibility that they will return a deferred (i.e., if you call them while they&#8217;re wrapped).</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2009/05/11/a-mixin-class-allowing-python-__init__-methods-to-work-with-twisted-deferreds/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A kinder and more consistent defer.inlineCallbacks</title>
		<link>http://blogs.fluidinfo.com/terry/2008/11/21/a-kinder-and-more-consistent-deferinlinecallbacks/</link>
		<comments>http://blogs.fluidinfo.com/terry/2008/11/21/a-kinder-and-more-consistent-deferinlinecallbacks/#comments</comments>
		<pubDate>Fri, 21 Nov 2008 18:20:47 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=378</guid>
		<description><![CDATA[Here&#8217;s a suggestion for making Twisted&#8216;s inlineCallbacks function decorator more consistent and less confusing. Let&#8217;s suppose you&#8217;re writing something like this: &#160; &#160; @inlineCallbacks &#160; &#160; def func&#40;&#41;: &#160; &#160; &#160; &#160; # Do something. &#160; &#160; result = func&#40;&#41; &#160; There are 2 things that could be better, IMO: 1. func may not yield. [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a suggestion for making <a href="http://twistedmatrix.com">Twisted</a>&#8216;s inlineCallbacks function decorator more consistent and less confusing.  Let&#8217;s suppose you&#8217;re writing something like this:</p>
<div class="dean_ch" style="white-space: nowrap;">
&nbsp; &nbsp; @inlineCallbacks<br />
&nbsp; &nbsp; <span class="kw1">def</span> func<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Do something.</span></p>
<p>&nbsp; &nbsp; result = func<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>There are 2 things that could be better, IMO:</p>
<p>1. func may not yield. In that case, you get an AttributeError when inlineCallbacks tries to send() to something that&#8217;s not a generator. Or worse, the call to send might actually work, and do who knows what. I.e., func() could return an object with a send method but which is not a generator. For some fun, run some code that calls the following decorated function (see if you can figure out what will happen before you do):</p>
<div class="dean_ch" style="white-space: nowrap;">
&nbsp; &nbsp; @defer.<span class="me1">inlineCallbacks</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> f<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">class</span> yes<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> send<span class="br0">&#40;</span>x, y<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">print</span> <span class="st0">&#8216;yes&#8217;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># accidentally_destroy_the_universe_too()</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> yes<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>2. func might raise before it get to its first yield. In that case you&#8217;ll get an exception thrown when the inlineCallbacks decorator tries to create the wrapper function:</p>
<pre>
    File "/usr/lib/python2.5/site-packages/twisted/internet/defer.py", line 813, in unwindGenerator
      return _inlineCallbacks(None, f(*args, **kwargs), Deferred())
</pre>
<p>There&#8217;s a simple and consistent way to handle both of these. Just have inlineCallbacks do some initial work based on what it has been passed:</p>
<div class="dean_ch" style="white-space: nowrap;">
&nbsp; &nbsp; <span class="kw1">def</span> altInlineCallbacks<span class="br0">&#40;</span>f<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> unwindGenerator<span class="br0">&#40;</span>*args, **kwargs<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; deferred = defer.<span class="me1">Deferred</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = f<span class="br0">&#40;</span>*args, **kwargs<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">Exception</span>, e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; deferred.<span class="me1">errback</span><span class="br0">&#40;</span>e<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> deferred<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">isinstance</span><span class="br0">&#40;</span>result, <span class="kw3">types</span>.<span class="me1">GeneratorType</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> defer._inlineCallbacks<span class="br0">&#40;</span><span class="kw2">None</span>, result, deferred<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; deferred.<span class="me1">callback</span><span class="br0">&#40;</span>result<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> deferred</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> mergeFunctionMetadata<span class="br0">&#40;</span>f, unwindGenerator<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>This has the advantage that (barring e.g., a KeyboardInterrupt in the middle of things) you&#8217;ll *always* get a deferred back when you call an inlineCallbacks decorated function. That deferred might have already called or erred back (corresponding to cases 1 and 2 above).</p>
<p>I&#8217;m going to use this version of inlineCallbacks in my code.  There&#8217;s a case for it making it into Twisted itself: inlinecallbacks is already cryptic enough in its operation that anything we can do to make its operation more uniform and less surprising, the better.</p>
<p>You might think that case 1 rarely comes up. But I&#8217;ve hit it a few times, usually when commenting out sections of code for testing. If you accidentally comment out the last yield in func, it no longer returns a generator and that causes a different error.</p>
<p>And case 2 happens to me too. Having inlinecallbacks try/except the call to func is nicer because it means I don&#8217;t have to be quite so defensive in coding. So instead of me having to write</p>
<div class="dean_ch" style="white-space: nowrap;">
&nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; d = func<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">Exception</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1"># Do something.</span><br />
&nbsp;</div>
<p>and try to figure out what happened if an exception fired, I can just write d = func() and add errbacks as I please (they then have to figure out what happened).  The (slight?) disadvantage to my suggestion is that with the above try/except fragment you can tell if the call to func() raised before ever yielding. You can detect that, if you need to, with my approach if you&#8217;re not offended by looking at d.called immediately after calling func.</p>
<p>The alternate approach also helps if you&#8217;re a novice, or simply being lazy/careless/forgetful, and writing:</p>
<div class="dean_ch" style="white-space: nowrap;">
&nbsp; &nbsp; d = func<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; d.<span class="me1">addCallback</span><span class="br0">&#40;</span>ok<span class="br0">&#41;</span><br />
&nbsp; &nbsp; d.<span class="me1">addErrback</span><span class="br0">&#40;</span>not_ok<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>thinking you have your ass covered, but you actually don&#8217;t (due to case 2).</p>
<p>There&#8217;s some test code <a href="/terry-other/altInlineCallbacks.py">here</a> that illustrates all this.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2008/11/21/a-kinder-and-more-consistent-deferinlinecallbacks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Python metaclass for Twisted allowing __init__ to return a Deferred</title>
		<link>http://blogs.fluidinfo.com/terry/2008/11/03/a-python-metaclass-for-twisted-allowing-__init__-to-return-a-deferred/</link>
		<comments>http://blogs.fluidinfo.com/terry/2008/11/03/a-python-metaclass-for-twisted-allowing-__init__-to-return-a-deferred/#comments</comments>
		<pubDate>Sun, 02 Nov 2008 23:33:01 +0000</pubDate>
		<dc:creator>terry</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[tech]]></category>
		<category><![CDATA[twisted]]></category>
		<category><![CDATA[Deferred]]></category>
		<category><![CDATA[metaclass]]></category>
		<category><![CDATA[Twisted]]></category>
		<category><![CDATA[__init__]]></category>

		<guid isPermaLink="false">http://blogs.fluidinfo.com/terry/?p=281</guid>
		<description><![CDATA[OK, I admit, this is geeky. But we&#8217;ve all run into the situation in which you&#8217;re using Python and Twisted, and you&#8217;re writing a new class and you want to call something from the __init method that returns a Deferred. This is a problem. The __init method is not allowed to return a value, let [...]]]></description>
			<content:encoded><![CDATA[<p>OK, I admit, this is geeky.</p>
<p>But we&#8217;ve all run into the situation in which you&#8217;re using <a href="http://www.python.org/">Python</a> and <a href="http://twistedmatrix.com/">Twisted</a>, and you&#8217;re writing a new class and you want to call something from the <code>__init</code> method that returns a Deferred. This is a problem. The <code>__init</code> method is not allowed to return a value, let alone a Deferred. While you could just call the Deferred-returning function from inside your <code>__init</code>, there&#8217;s no guarantee of when that Deferred will fire. Seeing as you&#8217;re in your <code>__init</code>  method, it&#8217;s a good bet that you need that function to have done its thing before you let anyone get their hands on an instance of your class.</p>
<p>For example, consider a class that provides access to a database table. You want the <code>__init__</code> method to create the table in the db if it doesn&#8217;t already exist. But if you&#8217;re using Twisted&#8217;s <code><a href="http://twistedmatrix.com/documents/current/api/twisted.enterprise.adbapi.html">twisted.enterprise.adbapi</a></code> class, the <code>runInteraction</code> method returns a Deferred. You can call it to create the tables, but you don&#8217;t want the instance of your class back in the hands of whoever&#8217;s creating it until the table is created. Otherwise they might call a method on the instance that expects the table to be there.</p>
<p>A cumbersome solution would be to add a callback to the Deferred you get back from <code>runInteraction</code> and have that callback add an attribute to <code>self</code> to indicate that it is safe to proceed. Then all your class methods that access the db table would have to check to see if the attribute was on <code>self</code>, and take some alternate action if not. That&#8217;s going to get ugly very fast <em>plus</em>, your caller has to deal with you potentially not being ready.</p>
<p>I ran into this problem a couple of days ago and after scratching my head for a while I came up with an idea for how to solve this pretty cleanly via a <a href="http://www.ibm.com/developerworks/linux/library/l-pymeta.html">Python metaclass</a>. Here&#8217;s the metaclass code:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">from</span> twisted.<span class="me1">internet</span> <span class="kw1">import</span> defer</p>
<p><span class="kw1">class</span> TxDeferredInitMeta<span class="br0">&#40;</span><span class="kw2">type</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__new__</span><span class="br0">&#40;</span>mcl, classname, bases, classdict<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; hidden = <span class="st0">&#8216;__hidden__&#8217;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; instantiate = <span class="st0">&#8216;__instantiate__&#8217;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> name <span class="kw1">in</span> hidden, instantiate:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> name <span class="kw1">in</span> classdict:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">raise</span> <span class="kw2">Exception</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&#8216;Class %s contains an illegally-named %s method&#8217;</span> %<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span>classname, name<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; origInit = classdict<span class="br0">&#91;</span><span class="st0">&#8216;__init__&#8217;</span><span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyError</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; origInit = <span class="kw1">lambda</span> <span class="kw2">self</span>: <span class="kw2">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> newInit<span class="br0">&#40;</span><span class="kw2">self</span>, *args, **kw<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hiddenDict = <span class="kw2">dict</span><span class="br0">&#40;</span>args=args, kw=kw, <span class="kw4">__init__</span>=origInit<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">setattr</span><span class="br0">&#40;</span><span class="kw2">self</span>, hidden, hiddenDict<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> _instantiate<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">def</span> addSelf<span class="br0">&#40;</span>result<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><span class="kw2">self</span>, result<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hiddenDict = <span class="kw2">getattr</span><span class="br0">&#40;</span><span class="kw2">self</span>, hidden<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; d = defer.<span class="me1">maybeDeferred</span><span class="br0">&#40;</span>hiddenDict<span class="br0">&#91;</span><span class="st0">&#8216;__init__&#8217;</span><span class="br0">&#93;</span>, <span class="kw2">self</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *hiddenDict<span class="br0">&#91;</span><span class="st0">&#8216;args&#8217;</span><span class="br0">&#93;</span>, **hiddenDict<span class="br0">&#91;</span><span class="st0">&#8216;kw&#8217;</span><span class="br0">&#93;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> d.<span class="me1">addCallback</span><span class="br0">&#40;</span>addSelf<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; classdict<span class="br0">&#91;</span><span class="st0">&#8216;__init__&#8217;</span><span class="br0">&#93;</span> = newInit<br />
&nbsp; &nbsp; &nbsp; &nbsp; classdict<span class="br0">&#91;</span>instantiate<span class="br0">&#93;</span> = _instantiate<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">super</span><span class="br0">&#40;</span>TxDeferredInitMeta, mcl<span class="br0">&#41;</span>.<span class="kw4">__new__</span><span class="br0">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mcl, classname, bases, classdict<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>I&#8217;m not going to explain what it does here. If it&#8217;s not clear and you want to know, send me mail or post a comment. But I&#8217;ll show you how you use it in practice. It&#8217;s kind of weird, but it makes sense once you get used to it.</p>
<p>First, we make a class whose metaclass is TxDeferredInitMeta and whose <code>__init__</code> method returns a deferred:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">class</span> MyClass<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw4">__metaclass__</span> = TxDeferredInitMeta<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; d = aFuncReturningADeferred<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> d<br />
&nbsp;</div>
<p>Having <code>__init__</code> return anything other than <code>None</code> is illegal in normal Python classes. But this is not a normal Python class, as you will now see.</p>
<p>Given our class, we use it like this:</p>
<div class="dean_ch" style="white-space: nowrap;">
<span class="kw1">def</span> cb<span class="br0">&#40;</span><span class="br0">&#40;</span>instance, result<span class="br0">&#41;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="co1"># instance is an instance of MyClass</span><br />
&nbsp; &nbsp; <span class="co1"># result is from the callback chain of aFuncReturningADeferred</span><br />
&nbsp; &nbsp; <span class="kw1">pass</span></p>
<p>d = MyClass<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d.__instantiate__<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
d.<span class="me1">addCallback</span><span class="br0">&#40;</span>cb<span class="br0">&#41;</span><br />
&nbsp;</div>
<p>That may look pretty funky, but if you&#8217;re used to Twisted it wont seem too bizarre. What&#8217;s happening is that when you ask to make an instance of MyClass, you get back an instance of a regular Python class. It has a method called <code>__instantiate__</code> that returns a Deferred. You add a callback to that Deferred and that callback is eventually passed two things. The first is an instance of MyClass, as you requested. The second is the result that came down the callback chain from the Deferred that was returned by the <code>__init__</code> method you wrote in MyClass.</p>
<p>The net result is that you have the value of the Deferred and you have your instance of MyClass. It&#8217;s safe to go ahead and use the instance because you know the Deferred has been called.  It will probably seem a bit odd to get your instance later as a result of a Deferred firing, but that&#8217;s perfectly in keeping with the Twisted way.</p>
<p>That&#8217;s it for now. You can grab the code and a <a href="http://twistedmatrix.com/documents/current/api/twisted.trial.html">trial</a> test suite to put it through its paces at <a href="http://foss.fluidinfo.com/txDeferredInitMeta.zip">http://foss.fluidinfo.com/txDeferredInitMeta.zip</a>. The code could be cleaned up somewhat, and made more general. There is a caveat to using it &#8211; your class can&#8217;t have <code>__hidden__</code> or <code>__instantiate__</code> methods. That could be improved. But I&#8217;m not going to bother for now, unless someone cares.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogs.fluidinfo.com/terry/2008/11/03/a-python-metaclass-for-twisted-allowing-__init__-to-return-a-deferred/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

