1
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
3
<title>Twisted Documentation: Generating Deferreds</title>
4
<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
8
<h1 class="title">Generating Deferreds</h1>
9
<div class="toc"><ol><li><a href="#auto0">Class overview</a></li><ul><li><a href="#auto1">Basic Callback Functions</a></li></ul><li><a href="#auto2">What Deferreds don't do: make your code asynchronous</a></li><li><a href="#auto3">Advanced Processing Chain Control</a></li><li><a href="#auto4">Returning Deferreds from synchronous functions</a></li><li><a href="#auto5">Integrating blocking code with Twisted</a></li><li><a href="#auto6">Possible sources of error</a></li><ul><li><a href="#auto7">Firing Deferreds more than once is impossible</a></li><li><a href="#auto8">Synchronous callback execution</a></li></ul></ol></div>
14
<p><code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.Deferred.html" title="twisted.internet.defer.Deferred">Deferred</a></code> objects are
15
signals that a function you have called does not yet have the data you want
16
available. When a function returns a Deferred object, your calling function
17
attaches callbacks to it to handle the data when available.</p>
19
<p>This document addresses the other half of the question: writing functions
20
that return Deferreds, that is, constructing Deferred objects, arranging for
21
them to be returned immediately without blocking until data is available, and
22
firing their callbacks when the data is available.</p>
24
<p>This document assumes that you are familiar with the asynchronous model used
25
by Twisted, and with <a href="defer.html" shape="rect">using deferreds returned by functions</a>
28
<a name="class" shape="rect"/>
30
<h2>Class overview<a name="auto0"/></h2>
32
<p>This is an overview API reference for Deferred from the point of creating a
33
Deferred and firing its callbacks and errbacks. It is not meant to be a
34
substitute for the docstrings in the Deferred class, but can provide
35
guidelines for its use.</p>
37
<p>There is a parallel overview of functions used by calling function which
38
the Deferred is returned to at <a href="defer.html#class" shape="rect">Using Deferreds</a>.</p>
40
<h3>Basic Callback Functions<a name="auto1"/></h3>
44
<code class="py-prototype">callback(result)</code>
46
<p>Run success callbacks with the given result. <em>This
47
can only be run once.</em> Later calls to this or
48
<code>errback</code> will raise <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.AlreadyCalledError.html" title="twisted.internet.defer.AlreadyCalledError">twisted.internet.defer.AlreadyCalledError</a></code>.
49
If further callbacks or errbacks are added after this
50
point, addCallbacks will run the callbacks immediately.</p>
54
<code class="py-prototype">errback(failure)</code>
56
<p>Run error callbacks with the given failure. <em>This can
57
only be run once.</em> Later calls to this or
58
<code>callback</code> will raise <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.AlreadyCalledError.html" title="twisted.internet.defer.AlreadyCalledError">twisted.internet.defer.AlreadyCalledError</a></code>.
59
If further callbacks or errbacks are added after this
60
point, addCallbacks will run the callbacks immediately.</p>
64
<h2>What Deferreds don't do: make your code asynchronous<a name="auto2"/></h2>
66
<p><em>Deferreds do not make the code magically not block.</em></p>
68
<p>Let's take this function as an example:</p>
70
<pre class="python"><p class="py-linenumber"> 1
116
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
118
<span class="py-src-variable">TARGET</span> = <span class="py-src-number">10000</span>
120
<span class="py-src-keyword">def</span> <span class="py-src-identifier">largeFibonnaciNumber</span>():
121
<span class="py-src-comment"># create a Deferred object to return:</span>
122
<span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
124
<span class="py-src-comment"># calculate the ten thousandth Fibonnaci number</span>
126
<span class="py-src-variable">first</span> = <span class="py-src-number">0</span>
127
<span class="py-src-variable">second</span> = <span class="py-src-number">1</span>
129
<span class="py-src-keyword">for</span> <span class="py-src-variable">i</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">xrange</span>(<span class="py-src-variable">TARGET</span> - <span class="py-src-number">1</span>):
130
<span class="py-src-variable">new</span> = <span class="py-src-variable">first</span> + <span class="py-src-variable">second</span>
131
<span class="py-src-variable">first</span> = <span class="py-src-variable">second</span>
132
<span class="py-src-variable">second</span> = <span class="py-src-variable">new</span>
133
<span class="py-src-keyword">if</span> <span class="py-src-variable">i</span> % <span class="py-src-number">100</span> == <span class="py-src-number">0</span>:
134
<span class="py-src-keyword">print</span> <span class="py-src-string">"Progress: calculating the %dth Fibonnaci number"</span> % <span class="py-src-variable">i</span>
136
<span class="py-src-comment"># give the Deferred the answer to pass to the callbacks:</span>
137
<span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-variable">second</span>)
139
<span class="py-src-comment"># return the Deferred with the answer:</span>
140
<span class="py-src-keyword">return</span> <span class="py-src-variable">d</span>
142
<span class="py-src-keyword">import</span> <span class="py-src-variable">time</span>
144
<span class="py-src-variable">timeBefore</span> = <span class="py-src-variable">time</span>.<span class="py-src-variable">time</span>()
146
<span class="py-src-comment"># call the function and get our Deferred</span>
147
<span class="py-src-variable">d</span> = <span class="py-src-variable">largeFibonnaciNumber</span>()
149
<span class="py-src-variable">timeAfter</span> = <span class="py-src-variable">time</span>.<span class="py-src-variable">time</span>()
151
<span class="py-src-keyword">print</span> <span class="py-src-string">"Total time taken for largeFibonnaciNumber call: %0.3f seconds"</span> %
152
(<span class="py-src-variable">timeAfter</span> - <span class="py-src-variable">timeBefore</span>)
154
<span class="py-src-comment"># add a callback to it to print the number</span>
156
<span class="py-src-keyword">def</span> <span class="py-src-identifier">printNumber</span>(<span class="py-src-parameter">number</span>):
157
<span class="py-src-keyword">print</span> <span class="py-src-string">"The %dth Fibonacci number is %d"</span> % (<span class="py-src-variable">TARGET</span>, <span class="py-src-variable">number</span>)
159
<span class="py-src-keyword">print</span> <span class="py-src-string">"Adding the callback now."</span>
161
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">printNumber</span>)
164
<p>You will notice that despite creating a Deferred in the
165
<code>largeFibonnaciNumber</code> function, these things happened:</p>
167
<li>the "Total time taken for largeFibonnaciNumber call" output
168
shows that the function did not return immediately as asynchronous functions
169
are expected to do; and</li>
170
<li>rather than the callback being added before the result was available and
171
called after the result is available, it isn't even added until after the
172
calculation has been completed.</li>
175
<p> The function completed its calculation before returning, blocking the
176
process until it had finished, which is exactly what asynchronous functions
177
are not meant to do. Deferreds are not a non-blocking talisman: they are a
178
signal for asynchronous functions to <em>use</em> to pass results onto
179
callbacks, but using them does not guarantee that you have an asynchronous
183
<h2>Advanced Processing Chain Control<a name="auto3"/></h2>
187
<code class="py-prototype">pause()</code>
189
<p>Cease calling any methods as they are added, and do not
190
respond to <code>callback</code>, until
191
<code>self.unpause()</code> is called.</p>
195
<code class="py-prototype">unpause()</code>
197
<p>If <code>callback</code> has been called on this
198
Deferred already, call all the callbacks that have been
199
added to this Deferred since <code>pause</code> was
202
<p>Whether it was called or not, this will put this
203
Deferred in a state where further calls to
204
<code>addCallbacks</code> or <code>callback</code> will
209
<h2>Returning Deferreds from synchronous functions<a name="auto4"/></h2>
211
<p>Sometimes you might wish to return a Deferred from a synchronous function.
212
There are several reasons why, the major two are maintaining API compatibility
213
with another version of your function which returns a Deferred, or allowing
214
for the possiblity that in the future your function might need to be
217
<p>In the <a href="defer.html" shape="rect">Using Deferreds</a> reference, we gave the
218
following example of a synchronous function:</p>
220
<div class="py-listing"><pre><p class="py-linenumber">1
225
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">synchronousIsValidUser</span>(<span class="py-src-parameter">user</span>):
226
<span class="py-src-string">'''
227
Return true if user is a valid user, false otherwise
229
<span class="py-src-keyword">return</span> <span class="py-src-variable">user</span> <span class="py-src-keyword">in</span> [<span class="py-src-string">"Alice"</span>, <span class="py-src-string">"Angus"</span>, <span class="py-src-string">"Agnes"</span>]
230
</pre><div class="caption">Source listing - <a href="listings/deferred/synch-validation.py"><span class="filename">listings/deferred/synch-validation.py</span></a></div></div>
232
<p>While we can require that callers of our function wrap our synchronous
233
result in a Deferred using <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.maybeDeferred.html" title="twisted.internet.defer.maybeDeferred">maybeDeferred</a></code>, for the sake of API
234
compatibility it is better to return a Deferred ourself using <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.succeed.html" title="twisted.internet.defer.succeed">defer.succeed</a></code>:</p>
236
<pre class="python"><p class="py-linenumber"> 1
248
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
250
<span class="py-src-keyword">def</span> <span class="py-src-identifier">immediateIsValidUser</span>(<span class="py-src-parameter">user</span>):
251
<span class="py-src-string">'''
252
Returns a Deferred resulting in true if user is a valid user, false
256
<span class="py-src-variable">result</span> = <span class="py-src-variable">user</span> <span class="py-src-keyword">in</span> [<span class="py-src-string">"Alice"</span>, <span class="py-src-string">"Angus"</span>, <span class="py-src-string">"Agnes"</span>]
258
<span class="py-src-comment"># return a Deferred object already called back with the value of result</span>
259
<span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">result</span>)
262
<p>There is an equivalent <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.fail.html" title="twisted.internet.defer.fail">defer.fail</a></code> method to return a Deferred with the
263
errback chain already fired.</p>
265
<h2>Integrating blocking code with Twisted<a name="auto5"/></h2>
267
<p>At some point, you are likely to need to call a blocking function: many
268
functions in third party libraries will have long running blocking functions.
269
There is no way to 'force' a function to be asynchronous: it must be written
270
that way specifically. When using Twisted, your own code should be
271
asynchronous, but there is no way to make third party functions asynchronous
272
other than rewriting them.</p>
274
<p>In this case, Twisted provides the ability to run the blocking code in a
275
separate thread rather than letting it block your application. The <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.threads.deferToThread.html" title="twisted.internet.threads.deferToThread">twisted.internet.threads.deferToThread</a></code> function will set up
276
a thread to run your blocking function, return a Deferred and later fire that
277
Deferred when the thread completes.</p>
279
<p>Let's assume our <code class="python">largeFibonnaciNumber</code> function
280
from above is in a third party library (returning the result of the
281
calculation, not a Deferred) and is not easily modifiable to be finished in
282
discrete blocks. This example shows it being called in a thread, unlike in the
283
earlier section we'll see that the operation does not block our entire
286
<pre class="python"><p class="py-linenumber"> 1
331
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">largeFibonnaciNumber</span>():
332
<span class="py-src-string">"""
333
Represent a long running blocking function by calculating
334
the TARGETth Fibonnaci number
335
"""</span>
336
<span class="py-src-variable">TARGET</span> = <span class="py-src-number">10000</span>
338
<span class="py-src-variable">first</span> = <span class="py-src-number">0</span>
339
<span class="py-src-variable">second</span> = <span class="py-src-number">1</span>
341
<span class="py-src-keyword">for</span> <span class="py-src-variable">i</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">xrange</span>(<span class="py-src-variable">TARGET</span> - <span class="py-src-number">1</span>):
342
<span class="py-src-variable">new</span> = <span class="py-src-variable">first</span> + <span class="py-src-variable">second</span>
343
<span class="py-src-variable">first</span> = <span class="py-src-variable">second</span>
344
<span class="py-src-variable">second</span> = <span class="py-src-variable">new</span>
346
<span class="py-src-keyword">return</span> <span class="py-src-variable">second</span>
348
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">threads</span>, <span class="py-src-variable">reactor</span>
350
<span class="py-src-keyword">def</span> <span class="py-src-identifier">fibonacciCallback</span>(<span class="py-src-parameter">result</span>):
351
<span class="py-src-string">"""
352
Callback which manages the largeFibonnaciNumber result by
354
"""</span>
355
<span class="py-src-keyword">print</span> <span class="py-src-string">"largeFibonnaciNumber result ="</span>, <span class="py-src-variable">result</span>
356
<span class="py-src-comment"># make sure the reactor stops after the callback chain finishes,</span>
357
<span class="py-src-comment"># just so that this example terminates</span>
358
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>()
360
<span class="py-src-keyword">def</span> <span class="py-src-identifier">run</span>():
361
<span class="py-src-string">"""
362
Run a series of operations, deferring the largeFibonnaciNumber
363
operation to a thread and performing some other operations after
365
"""</span>
366
<span class="py-src-comment"># get our Deferred which will be called with the largeFibonnaciNumber result</span>
367
<span class="py-src-variable">d</span> = <span class="py-src-variable">threads</span>.<span class="py-src-variable">deferToThread</span>(<span class="py-src-variable">largeFibonnaciNumber</span>)
368
<span class="py-src-comment"># add our callback to print it out</span>
369
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">fibonacciCallback</span>)
370
<span class="py-src-keyword">print</span> <span class="py-src-string">"1st line after the addition of the callback"</span>
371
<span class="py-src-keyword">print</span> <span class="py-src-string">"2nd line after the addition of the callback"</span>
373
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
374
<span class="py-src-variable">run</span>()
375
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
378
<h2>Possible sources of error<a name="auto6"/></h2>
380
<p>Deferreds greatly simplify the process of writing asynchronous code by
381
providing a standard for registering callbacks, but there are some subtle and
382
sometimes confusing rules that you need to follow if you are going to use
383
them. This mostly applies to people who are writing new systems that use
384
Deferreds internally, and not writers of applications that just add callbacks
385
to Deferreds produced and processed by other systems. Nevertheless, it is good
388
<h3>Firing Deferreds more than once is impossible<a name="auto7"/></h3>
390
<p>Deferreds are one-shot. You can only call <code>Deferred.callback</code> or
391
<code>Deferred.errback</code> once. The processing chain continues each time
392
you add new callbacks to an already-called-back-to Deferred.</p>
394
<h3>Synchronous callback execution<a name="auto8"/></h3>
396
<p>If a Deferred already has a result available, addCallback
397
<strong>may</strong> call the callback synchronously: that is, immediately
398
after it's been added. In situations where callbacks modify state, it is
399
might be desirable for the chain of processing to halt until all callbacks are
400
added. For this, it is possible to <code>pause</code> and <code>unpause</code>
401
a Deferred's processing chain while you are adding lots of callbacks.</p>
403
<p>Be careful when you use these methods! If you <code>pause</code> a
404
Deferred, it is <em>your</em> responsibility to make sure that you unpause it.
405
The function adding the callbacks must unpause a paused Deferred, it should
406
<em>never</em> be the responsibility of the code that actually fires the
407
callback chain by calling <code>callback</code> or <code>errback</code> as
408
this would negate its usefulness!</p>
412
<p><a href="index.html">Index</a></p>
413
<span class="version">Version: 10.0.0</span>
b'\\ No newline at end of file'