1
<?xml version="1.0"?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head><title>Twisted Documentation: Deferred Reference</title><link href="stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Deferred Reference</h1><div class="toc"><ol><li><a href="#auto0">Callbacks</a></li><ul><li><a href="#auto1">Multiple callbacks</a></li><li><a href="#auto2">Visual Explanation</a></li></ul><li><a href="#auto3">Errbacks</a></li><ul><li><a href="#auto4">Unhandled Errors</a></li></ul><li><a href="#auto5">Handling either synchronous or asynchronous results</a></li><ul><li><a href="#auto6">Handling possible Deferreds in the library code</a></li></ul><li><a href="#auto7">DeferredList</a></li><ul><li><a href="#auto8">Other behaviours</a></li></ul><li><a href="#auto9">Class Overview</a></li><ul><li><a href="#auto10">Basic Callback Functions</a></li><li><a href="#auto11">Chaining Deferreds</a></li></ul><li><a href="#auto12">See also</a></li></ol></div><div class="content"><span></span><p>This document is a guide to the behaviour of the <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.defer.Deferred.html" title="twisted.internet.defer.Deferred">twisted.internet.defer.Deferred</a></code> object, and to various
3
ways you can use them when they are returned by functions.</p><p>This document assumes that you are familiar with the basic principle that
1
<?xml version="1.0" encoding="utf-8"?>
3
PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'
4
'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>
5
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
7
<title>Twisted Documentation: Deferred Reference</title>
8
<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
11
<body bgcolor="white">
12
<h1 class="title">Deferred Reference</h1>
13
<div class="toc"><ol><li><a href="#auto0">Deferreds</a></li><li><a href="#auto1">Callbacks</a></li><ul><li><a href="#auto2">Multiple callbacks</a></li><li><a href="#auto3">Visual Explanation</a></li></ul><li><a href="#auto4">Errbacks</a></li><ul><li><a href="#auto5">Unhandled Errors</a></li></ul><li><a href="#auto6">Handling either synchronous or asynchronous results</a></li><ul><li><a href="#auto7">Handling possible Deferreds in the library code</a></li></ul><li><a href="#auto8">DeferredList</a></li><ul><li><a href="#auto9">Other behaviours</a></li></ul><li><a href="#auto10">Class Overview</a></li><ul><li><a href="#auto11">Basic Callback Functions</a></li><li><a href="#auto12">Chaining Deferreds</a></li></ul><li><a href="#auto13">See also</a></li></ol></div>
18
<p>This document is a guide to the behaviour of the <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.defer.Deferred.html" title="twisted.internet.defer.Deferred">twisted.internet.defer.Deferred</a></code> object, and to various
19
ways you can use them when they are returned by functions.</p>
21
<p>This document assumes that you are familiar with the basic principle that
4
22
the Twisted framework is structured around: asynchronous, callback-based
5
23
programming, where instead of having blocking code in your program or using
6
24
threads to run blocking code, you have functions that return immediately and
7
then begin a callback chain when data is available.</p><p>See these documents for more information:</p><ul><li><a href="async.html">Asynchronous Programming with Twisted</a></li></ul><p>
25
then begin a callback chain when data is available.</p>
8
28
After reading this document, the reader should expect to be able to
9
29
deal with most simple APIs in Twisted and Twisted-using code that
11
</p><ul><li>what sorts of things you can do when you get a Deferred from a
12
function call; and</li><li>how you can write your code to robustly handle errors in Deferred
13
code.</li></ul><p>Unless you're already very familiar with asynchronous programming,
14
it's strongly recommended you read
15
the <a href="async.html#deferreds">Deferreds section</a> of the
16
Asynchronous programming document to get an idea of why Deferreds
18
</p><h2>Callbacks<a name="auto0"></a></h2><p>A <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.defer.Deferred.html" title="twisted.internet.defer.Deferred">twisted.internet.defer.Deferred</a></code> is a promise that
34
<li>what sorts of things you can do when you get a Deferred from a
35
function call; and</li>
36
<li>how you can write your code to robustly handle errors in Deferred
40
<a name="deferreds" shape="rect"/>
41
<h2>Deferreds<a name="auto0"/></h2>
43
<p>Twisted uses the <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.defer.Deferred.html" title="twisted.internet.defer.Deferred">Deferred</a></code> object to manage the callback
44
sequence. The client application attaches a series of functions to the
45
deferred to be called in order when the results of the asychronous request are
46
available (this series of functions is known as a series of
47
<strong>callbacks</strong>, or a <strong>callback chain</strong>), together
48
with a series of functions to be called if there is an error in the
49
asychronous request (known as a series of <strong>errbacks</strong> or an
50
<strong>errback chain</strong>). The asychronous library code calls the first
51
callback when the result is available, or the first errback when an error
52
occurs, and the <code>Deferred</code> object then hands the results of each
53
callback or errback function to the next function in the chain.</p>
55
<h2>Callbacks<a name="auto1"/></h2>
57
<p>A <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.defer.Deferred.html" title="twisted.internet.defer.Deferred">twisted.internet.defer.Deferred</a></code> is a promise that
19
58
a function will at some point have a result. We can attach callback functions
20
59
to a Deferred, and once it gets a result these callbacks will be called. In
21
60
addition Deferreds allow the developer to register a callback for an error,
22
61
with the default behavior of logging the error. The deferred mechanism
23
62
standardizes the application programmer's interface with all sorts of
24
blocking or delayed operations.</p><pre class="python">
25
<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">reactor</span>, <span class="py-src-variable">defer</span>
63
blocking or delayed operations.</p>
65
<pre class="python"><p class="py-linenumber"> 1
94
</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">reactor</span>, <span class="py-src-variable">defer</span>
27
96
<span class="py-src-keyword">def</span> <span class="py-src-identifier">getDummyData</span>(<span class="py-src-parameter">x</span>):
28
97
<span class="py-src-string">"""
110
248
<span class="py-src-keyword">import</span> <span class="py-src-variable">sys</span>
111
249
<span class="py-src-variable">sys</span>.<span class="py-src-variable">stderr</span>.<span class="py-src-variable">write</span>(<span class="py-src-variable">str</span>(<span class="py-src-variable">failure</span>))
113
<span class="py-src-comment"># this series of callbacks and errbacks will print an error message
114
</span><span class="py-src-variable">g</span> = <span class="py-src-variable">Getter</span>()
251
<span class="py-src-comment"># this series of callbacks and errbacks will print an error message</span>
252
<span class="py-src-variable">g</span> = <span class="py-src-variable">Getter</span>()
115
253
<span class="py-src-variable">d</span> = <span class="py-src-variable">g</span>.<span class="py-src-variable">getDummyData</span>(<span class="py-src-number">3</span>)
116
254
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">printData</span>)
117
255
<span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">printError</span>)
119
<span class="py-src-comment"># this series of callbacks and errbacks will print "Result: 12"
120
</span><span class="py-src-variable">g</span> = <span class="py-src-variable">Getter</span>()
257
<span class="py-src-comment"># this series of callbacks and errbacks will print "Result: 12"</span>
258
<span class="py-src-variable">g</span> = <span class="py-src-variable">Getter</span>()
121
259
<span class="py-src-variable">d</span> = <span class="py-src-variable">g</span>.<span class="py-src-variable">getDummyData</span>(<span class="py-src-number">4</span>)
122
260
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">printData</span>)
123
261
<span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">printError</span>)
125
263
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">4</span>, <span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>); <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
126
</pre><h3>Visual Explanation<a name="auto2"></a></h3><div hlint="off" align="center"><img src="../img/deferred-attach.png" /></div><ol><li>Requesting method (data sink) requests data, gets
127
Deferred object.</li><li>Requesting method attaches callbacks to Deferred
128
object.</li></ol><img src="../img/deferred-process.png" hlint="off" align="left" /><ol><li>When the result is ready, give it to the Deferred
266
<h3>Visual Explanation<a name="auto3"/></h3>
268
<div align="center" hlint="off">
269
<img src="../img/deferred-attach.png"/>
273
<li>Requesting method (data sink) requests data, gets
274
Deferred object.</li>
276
<li>Requesting method attaches callbacks to Deferred
279
<img align="left" hlint="off" src="../img/deferred-process.png"/>
283
<li>When the result is ready, give it to the Deferred
129
284
object. <code>.callback(result)</code> if the operation succeeded,
130
285
<code>.errback(failure)</code> if it failed. Note that
131
<code>failure</code> is typically an instance of a <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">twisted.python.failure.Failure</a></code>
132
instance.</li><li>Deferred object triggers previously-added (call/err)back
286
<code>failure</code> is typically an instance of a <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">twisted.python.failure.Failure</a></code>
289
<li>Deferred object triggers previously-added (call/err)back
133
290
with the <code>result</code> or <code>failure</code>.
134
291
Execution then follows the following rules, going down the
135
292
chain of callbacks to be processed.
137
<ul><li>Result of the callback is always passed as the first
295
<li>Result of the callback is always passed as the first
138
296
argument to the next callback, creating a chain of
139
processors.</li><li>If a callback raises an exception, switch to
140
errback.</li><li>An unhandled failure gets passed down the line of
299
<li>If a callback raises an exception, switch to
302
<li>An unhandled failure gets passed down the line of
141
303
errbacks, this creating an asynchronous analog to a
142
304
series to a series of <code>except:</code>
143
statements.</li><li>If an errback doesn't raise an exception or return a
144
<code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">twisted.python.failure.Failure</a></code>
145
instance, switch to callback.</li></ul></li></ol><br hlint="off" clear="all" /><h2>Errbacks<a name="auto3"></a></h2><p>Deferred's error handling is modeled after Python's
307
<li>If an errback doesn't raise an exception or return a
308
<code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">twisted.python.failure.Failure</a></code>
309
instance, switch to callback.</li>
312
<br clear="all" hlint="off"/>
314
<h2>Errbacks<a name="auto4"/></h2>
316
<p>Deferred's error handling is modeled after Python's
146
317
exception handling. In the case that no errors occur, all the
147
callbacks run, one after the other, as described above.</p><p>If the errback is called instead of the callback (e.g. because a DB query
148
raised an error), then a <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">twisted.python.failure.Failure</a></code> is passed into the first
318
callbacks run, one after the other, as described above.</p>
320
<p>If the errback is called instead of the callback (e.g. because a DB query
321
raised an error), then a <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">twisted.python.failure.Failure</a></code> is passed into the first
149
322
errback (you can add multiple errbacks, just like with callbacks). You can
150
323
think of your errbacks as being like <code class="python">except</code> blocks
151
of ordinary Python code.</p><p>Unless you explicitly <code class="python">raise</code> an error in except
324
of ordinary Python code.</p>
326
<p>Unless you explicitly <code class="python">raise</code> an error in except
152
327
block, the <code class="python">Exception</code> is caught and stops
153
328
propagating, and normal execution continues. The same thing happens with
154
329
errbacks: unless you explicitly <code class="python">return</code> a <code class="python">Failure</code> or (re-)raise an exception, the error stops
155
330
propagating, and normal callbacks continue executing from that point (using the
156
331
value returned from the errback). If the errback does returns a <code class="python">Failure</code> or raise an exception, then that is passed to the
157
next errback, and so on.</p><p><em>Note:</em> If an errback doesn't return anything, then it effectively
332
next errback, and so on.</p>
334
<p><em>Note:</em> If an errback doesn't return anything, then it effectively
158
335
returns <code class="python">None</code>, meaning that callbacks will continue
159
336
to be executed after this errback. This may not be what you expect to happen,
160
337
so be careful. Make sure your errbacks return a <code class="python">Failure</code> (probably the one that was passed to it), or a
161
meaningful return value for the next callback.</p><p>Also, <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">twisted.python.failure.Failure</a></code> instances have
338
meaningful return value for the next callback.</p>
340
<p>Also, <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">twisted.python.failure.Failure</a></code> instances have
162
341
a useful method called trap, allowing you to effectively do the equivalent
163
of:</p><pre class="python">
164
<span class="py-src-keyword">try</span>:
165
<span class="py-src-comment"># code that may throw an exception
166
</span> <span class="py-src-variable">cookSpamAndEggs</span>()
344
<pre class="python"><p class="py-linenumber">1
350
</p><span class="py-src-keyword">try</span>:
351
<span class="py-src-comment"># code that may throw an exception</span>
352
<span class="py-src-variable">cookSpamAndEggs</span>()
167
353
<span class="py-src-keyword">except</span> (<span class="py-src-variable">SpamException</span>, <span class="py-src-variable">EggException</span>):
168
<span class="py-src-comment"># Handle SpamExceptions and EggExceptions
170
</pre><p>You do this by:</p><pre class="python">
171
<span class="py-src-keyword">def</span> <span class="py-src-identifier">errorHandler</span>(<span class="py-src-parameter">failure</span>):
354
<span class="py-src-comment"># Handle SpamExceptions and EggExceptions</span>
358
<p>You do this by:</p>
359
<pre class="python"><p class="py-linenumber">1
365
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">errorHandler</span>(<span class="py-src-parameter">failure</span>):
172
366
<span class="py-src-variable">failure</span>.<span class="py-src-variable">trap</span>(<span class="py-src-variable">SpamException</span>, <span class="py-src-variable">EggException</span>)
173
<span class="py-src-comment"># Handle SpamExceptions and EggExceptions
367
<span class="py-src-comment"># Handle SpamExceptions and EggExceptions</span>
175
369
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">cookSpamAndEggs</span>)
176
370
<span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">errorHandler</span>)
177
</pre><p>If none of arguments passed to <code class="python">failure.trap</code>
373
<p>If none of arguments passed to <code class="python">failure.trap</code>
178
374
match the error encapsulated in that <code class="python">Failure</code>, then
179
it re-raises the error.</p><p>There's another potential <q>gotcha</q> here. There's a
180
method <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.defer.Deferred.addCallbacks.html" title="twisted.internet.defer.Deferred.addCallbacks">twisted.internet.defer.Deferred.addCallbacks</a></code>
181
which is similar to, but not exactly the same as, <code class="python">addCallback</code> followed by <code class="python">addErrback</code>. In particular, consider these two cases:</p><pre class="python">
182
<span class="py-src-comment"># Case 1
183
</span><span class="py-src-variable">d</span> = <span class="py-src-variable">getDeferredFromSomewhere</span>()
375
it re-raises the error.</p>
377
<p>There's another potential <q>gotcha</q> here. There's a
378
method <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.defer.Deferred.addCallbacks.html" title="twisted.internet.defer.Deferred.addCallbacks">twisted.internet.defer.Deferred.addCallbacks</a></code>
379
which is similar to, but not exactly the same as, <code class="python">addCallback</code> followed by <code class="python">addErrback</code>. In particular, consider these two cases:</p>
381
<pre class="python"><p class="py-linenumber"> 1
392
</p><span class="py-src-comment"># Case 1</span>
393
<span class="py-src-variable">d</span> = <span class="py-src-variable">getDeferredFromSomewhere</span>()
184
394
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">callback1</span>) <span class="py-src-comment"># A</span>
185
395
<span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">errback1</span>) <span class="py-src-comment"># B</span>
186
396
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">callback2</span>)
187
397
<span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">errback2</span>)
189
<span class="py-src-comment"># Case 2
190
</span><span class="py-src-variable">d</span> = <span class="py-src-variable">getDeferredFromSomewhere</span>()
399
<span class="py-src-comment"># Case 2</span>
400
<span class="py-src-variable">d</span> = <span class="py-src-variable">getDeferredFromSomewhere</span>()
191
401
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">callback1</span>, <span class="py-src-variable">errback1</span>) <span class="py-src-comment"># C</span>
192
402
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">callback2</span>, <span class="py-src-variable">errback2</span>)
193
</pre><p>If an error occurs in <code class="python">callback1</code>, then for Case 1
405
<p>If an error occurs in <code class="python">callback1</code>, then for Case 1
194
406
<code class="python">errback1</code> will be called with the failure. For Case
195
407
2, <code class="python">errback2</code> will be called. Be careful with your
196
callbacks and errbacks.</p><p>What this means in a practical sense is in Case 1, "A" will
408
callbacks and errbacks.</p>
410
<p>What this means in a practical sense is in Case 1, "A" will
197
411
handle a success condition from <code>getDeferredFromSomewhere</code>, and
198
412
"B" will handle any errors that occur <em>from either the upstream
199
413
source, or that occur in 'A'</em>. In Case 2, "C"'s errback1
200
414
<em>will only handle an error condition raised by
201
415
<code>getDeferredFromSomewhere</code></em>, it will not do any handling of
202
errors raised in callback1.</p><h3>Unhandled Errors<a name="auto4"></a></h3><p>If a Deferred is garbage-collected with an unhandled error (i.e. it would
416
errors raised in callback1.</p>
419
<h3>Unhandled Errors<a name="auto5"/></h3>
421
<p>If a Deferred is garbage-collected with an unhandled error (i.e. it would
203
422
call the next errback if there was one), then Twisted will write the error's
204
423
traceback to the log file. This means that you can typically get away with not
205
424
adding errbacks and still get errors logged. Be careful though; if you keep a
206
425
reference to the Deferred around, preventing it from being garbage-collected,
207
426
then you may never see the error (and your callbacks will mysteriously seem to
208
427
have never been called). If unsure, you should explicitly add an errback after
209
your callbacks, even if all you do is:</p><pre class="python">
210
<span class="py-src-comment"># Make sure errors get logged
211
</span><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">log</span>
428
your callbacks, even if all you do is:</p>
430
<pre class="python"><p class="py-linenumber">1
433
</p><span class="py-src-comment"># Make sure errors get logged</span>
434
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">log</span>
212
435
<span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">log</span>.<span class="py-src-variable">err</span>)
213
</pre><h2>Handling either synchronous or asynchronous results<a name="auto5"></a></h2><p>
438
<h2>Handling either synchronous or asynchronous results<a name="auto6"/></h2>
214
440
In some applications, there are functions that might be either asynchronous or
215
441
synchronous. For example, a user authentication function might be able to
216
442
check in memory whether a user is authenticated, allowing the authentication
240
476
alternatives: handling functions that might be synchronous or
241
477
asynchronous in the library function (<code>authenticateUser</code>)
242
478
or in the application code.
243
</p><h3>Handling possible Deferreds in the library code<a name="auto6"></a></h3><p>
481
<h3>Handling possible Deferreds in the library code<a name="auto7"/></h3>
244
484
Here is an example of a synchronous user authentication function that might be
245
485
passed to <code>authenticateUser</code>:
246
</p><div class="py-listing"><pre>
247
<span class="py-src-keyword">def</span> <span class="py-src-identifier">synchronousIsValidUser</span>(<span class="py-src-parameter">user</span>):
488
<div class="py-listing"><pre><p class="py-linenumber">1
493
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">synchronousIsValidUser</span>(<span class="py-src-parameter">user</span>):
248
494
<span class="py-src-string">'''
249
495
Return true if user is a valid user, false otherwise
251
497
<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>]
252
</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><p>
498
</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>
253
501
However, here's an <code>asynchronousIsValidUser</code> function that returns
255
</p><pre class="python">
256
<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">reactor</span>
505
<pre class="python"><p class="py-linenumber">1
511
</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">reactor</span>
258
513
<span class="py-src-keyword">def</span> <span class="py-src-identifier">asynchronousIsValidUser</span>(<span class="py-src-parameter">d</span>, <span class="py-src-parameter">user</span>):
259
514
<span class="py-src-variable">d</span> = <span class="py-src-variable">Deferred</span>()
260
515
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">callLater</span>(<span class="py-src-number">2</span>, <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</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>])
261
516
<span class="py-src-keyword">return</span> <span class="py-src-variable">d</span>
262
</pre><p> Our original implementation of <code>authenticateUser</code> expected
519
<p> Our original implementation of <code>authenticateUser</code> expected
263
520
<code>isValidUser</code> to be synchronous, but now we need to change it to handle both
264
521
synchronous and asynchronous implementations of <code>isValidUser</code>. For this, we
265
use <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.defer.maybeDeferred.html" title="twisted.internet.defer.maybeDeferred">maybeDeferred</a></code> to
522
use <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.defer.maybeDeferred.html" title="twisted.internet.defer.maybeDeferred">maybeDeferred</a></code> to
266
523
call <code>isValidUser</code>, ensuring that the result of <code>isValidUser</code> is a Deferred,
267
524
even if <code>isValidUser</code> is a synchronous function:
268
</p><pre class="python">
269
<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>
527
<pre class="python"><p class="py-linenumber"> 1
538
</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>
271
540
<span class="py-src-keyword">def</span> <span class="py-src-identifier">printResult</span>(<span class="py-src-parameter">result</span>):
272
541
<span class="py-src-keyword">if</span> <span class="py-src-variable">result</span>:
277
546
<span class="py-src-keyword">def</span> <span class="py-src-identifier">authenticateUser</span>(<span class="py-src-parameter">isValidUser</span>, <span class="py-src-parameter">user</span>):
278
547
<span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">maybeDeferred</span>(<span class="py-src-variable">isValidUser</span>, <span class="py-src-variable">user</span>)
279
548
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">printResult</span>)
281
552
Now <code>isValidUser</code> could be either <code>synchronousIsValidUser</code> or
282
553
<code>asynchronousIsValidUser</code>.
283
</p><p>It is also possible to modify <code>synchronousIsValidUser</code> to return
284
a Deferred, see <a href="gendefer.html">Generating Deferreds</a> for more
285
information.</p><h2>DeferredList<a name="auto7"></a></h2><p>Sometimes you want to be notified after several different events have all
556
<p>It is also possible to modify <code>synchronousIsValidUser</code> to return
557
a Deferred, see <a href="gendefer.html" shape="rect">Generating Deferreds</a> for more
560
<h2>DeferredList<a name="auto8"/></h2>
562
<p>Sometimes you want to be notified after several different events have all
286
563
happened, rather than waiting for each one individually. For example, you may
287
want to wait for all the connections in a list to close. <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.internet.defer.DeferredList.html" title="twisted.internet.defer.DeferredList">twisted.internet.defer.DeferredList</a></code> is the way to do
288
this.</p><p>To create a DeferredList from multiple Deferreds, you simply pass a list of
289
the Deferreds you want it to wait for:</p><pre class="python">
290
<span class="py-src-comment"># Creates a DeferredList
291
</span><span class="py-src-variable">dl</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">DeferredList</span>([<span class="py-src-variable">deferred1</span>, <span class="py-src-variable">deferred2</span>, <span class="py-src-variable">deferred3</span>])
292
</pre><p>You can now treat the DeferredList like an ordinary Deferred; you can call
564
want to wait for all the connections in a list to close. <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.internet.defer.DeferredList.html" title="twisted.internet.defer.DeferredList">twisted.internet.defer.DeferredList</a></code> is the way to do
567
<p>To create a DeferredList from multiple Deferreds, you simply pass a list of
568
the Deferreds you want it to wait for:</p>
569
<pre class="python"><p class="py-linenumber">1
571
</p><span class="py-src-comment"># Creates a DeferredList</span>
572
<span class="py-src-variable">dl</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">DeferredList</span>([<span class="py-src-variable">deferred1</span>, <span class="py-src-variable">deferred2</span>, <span class="py-src-variable">deferred3</span>])
575
<p>You can now treat the DeferredList like an ordinary Deferred; you can call
293
576
<code>addCallbacks</code> and so on. The DeferredList will call its callback
294
577
when all the deferreds have completed. The callback will be called with a list
295
of the results of the Deferreds it contains, like so:</p><pre class="python">
296
<span class="py-src-keyword">def</span> <span class="py-src-identifier">printResult</span>(<span class="py-src-parameter">result</span>):
578
of the results of the Deferreds it contains, like so:</p>
580
<pre class="python"><p class="py-linenumber"> 1
599
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">printResult</span>(<span class="py-src-parameter">result</span>):
297
600
<span class="py-src-keyword">for</span> (<span class="py-src-variable">success</span>, <span class="py-src-variable">value</span>) <span class="py-src-keyword">in</span> <span class="py-src-variable">result</span>:
298
601
<span class="py-src-keyword">if</span> <span class="py-src-variable">success</span>:
299
602
<span class="py-src-keyword">print</span> <span class="py-src-string">'Success:'</span>, <span class="py-src-variable">value</span>
307
610
<span class="py-src-variable">deferred1</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">'one'</span>)
308
611
<span class="py-src-variable">deferred2</span>.<span class="py-src-variable">errback</span>(<span class="py-src-variable">Exception</span>(<span class="py-src-string">'bang!'</span>))
309
612
<span class="py-src-variable">deferred3</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">'three'</span>)
310
<span class="py-src-comment"># At this point, dl will fire its callback, printing:
311
</span><span class="py-src-comment"># Success: one
312
</span><span class="py-src-comment"># Failure: bang!
313
</span><span class="py-src-comment"># Success: three
314
</span><span class="py-src-comment"># (note that defer.SUCCESS == True, and defer.FAILURE == False)
315
</span></pre><p>A standard DeferredList will never call errback, but failures in Deferreds
613
<span class="py-src-comment"># At this point, dl will fire its callback, printing:</span>
614
<span class="py-src-comment"># Success: one</span>
615
<span class="py-src-comment"># Failure: bang!</span>
616
<span class="py-src-comment"># Success: three</span>
617
<span class="py-src-comment"># (note that defer.SUCCESS == True, and defer.FAILURE == False)</span>
620
<p>A standard DeferredList will never call errback, but failures in Deferreds
316
621
passed to a DeferredList will still errback unless <code>consumeErrors</code>
317
622
is passed <code>True</code>. See below for more details about this and other
318
flags which modify the behavior of DeferredList.</p><div class="note"><strong>Note: </strong><p>If you want to apply callbacks to the individual Deferreds that
623
flags which modify the behavior of DeferredList.</p>
625
<div class="note"><strong>Note: </strong>
626
<p>If you want to apply callbacks to the individual Deferreds that
319
627
go into the DeferredList, you should be careful about when those callbacks
320
628
are added. The act of adding a Deferred to a DeferredList inserts a callback
321
629
into that Deferred (when that callback is run, it checks to see if the
322
630
DeferredList has been completed yet). The important thing to remember is
323
631
that it is <em>this callback</em> which records the value that goes into the
324
result list handed to the DeferredList's callback.</p><!-- TODO: add picture here: three columns of callback chains, with a value
325
being snarfed out of the middle of each and handed off to the DeferredList
326
--><p>Therefore, if you add a callback to the Deferred <em>after</em> adding the
632
result list handed to the DeferredList's callback.</p>
636
<p>Therefore, if you add a callback to the Deferred <em>after</em> adding the
327
637
Deferred to the DeferredList, the value returned by that callback will not
328
638
be given to the DeferredList's callback. To avoid confusion, we recommend not
329
adding callbacks to a Deferred once it has been used in a DeferredList.</p></div><pre class="python">
330
<span class="py-src-keyword">def</span> <span class="py-src-identifier">printResult</span>(<span class="py-src-parameter">result</span>):
639
adding callbacks to a Deferred once it has been used in a DeferredList.</p>
642
<pre class="python"><p class="py-linenumber"> 1
668
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">printResult</span>(<span class="py-src-parameter">result</span>):
331
669
<span class="py-src-keyword">print</span> <span class="py-src-variable">result</span>
332
670
<span class="py-src-keyword">def</span> <span class="py-src-identifier">addTen</span>(<span class="py-src-parameter">result</span>):
333
671
<span class="py-src-keyword">return</span> <span class="py-src-variable">result</span> + <span class="py-src-string">" ten"</span>
335
<span class="py-src-comment"># Deferred gets callback before DeferredList is created
336
</span><span class="py-src-variable">deferred1</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
673
<span class="py-src-comment"># Deferred gets callback before DeferredList is created</span>
674
<span class="py-src-variable">deferred1</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
337
675
<span class="py-src-variable">deferred2</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
338
676
<span class="py-src-variable">deferred1</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">addTen</span>)
339
677
<span class="py-src-variable">dl</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">DeferredList</span>([<span class="py-src-variable">deferred1</span>, <span class="py-src-variable">deferred2</span>])
340
678
<span class="py-src-variable">dl</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">printResult</span>)
341
679
<span class="py-src-variable">deferred1</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">"one"</span>) <span class="py-src-comment"># fires addTen, checks DeferredList, stores "one ten"</span>
342
680
<span class="py-src-variable">deferred2</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">"two"</span>)
343
<span class="py-src-comment"># At this point, dl will fire its callback, printing:
344
</span><span class="py-src-comment"># [(1, 'one ten'), (1, 'two')]
346
<span class="py-src-comment"># Deferred gets callback after DeferredList is created
347
</span><span class="py-src-variable">deferred1</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
681
<span class="py-src-comment"># At this point, dl will fire its callback, printing:</span>
682
<span class="py-src-comment"># [(1, 'one ten'), (1, 'two')]</span>
684
<span class="py-src-comment"># Deferred gets callback after DeferredList is created</span>
685
<span class="py-src-variable">deferred1</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
348
686
<span class="py-src-variable">deferred2</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
349
687
<span class="py-src-variable">dl</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">DeferredList</span>([<span class="py-src-variable">deferred1</span>, <span class="py-src-variable">deferred2</span>])
350
688
<span class="py-src-variable">deferred1</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">addTen</span>) <span class="py-src-comment"># will run *after* DeferredList gets its value</span>
351
689
<span class="py-src-variable">dl</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">printResult</span>)
352
690
<span class="py-src-variable">deferred1</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">"one"</span>) <span class="py-src-comment"># checks DeferredList, stores "one", fires addTen</span>
353
691
<span class="py-src-variable">deferred2</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">"two"</span>)
354
<span class="py-src-comment"># At this point, dl will fire its callback, printing:
355
</span><span class="py-src-comment"># [(1, 'one), (1, 'two')]
356
</span></pre><h3>Other behaviours<a name="auto8"></a></h3><p>DeferredList accepts three keyword arguments that modify its behaviour:
692
<span class="py-src-comment"># At this point, dl will fire its callback, printing:</span>
693
<span class="py-src-comment"># [(1, 'one), (1, 'two')]</span>
696
<h3>Other behaviours<a name="auto9"/></h3>
698
<p>DeferredList accepts three keyword arguments that modify its behaviour:
357
699
<code>fireOnOneCallback</code>, <code>fireOnOneErrback</code> and
358
700
<code>consumeErrors</code>. If <code>fireOnOneCallback</code> is set, the
359
701
DeferredList will immediately call its callback as soon as any of its Deferreds
361
703
as soon as any of the Deferreds call their errback. Note that DeferredList is
362
704
still one-shot, like ordinary Deferreds, so after a callback or errback has been
363
705
called the DeferredList will do nothing further (it will just silently ignore
364
any other results from its Deferreds).</p><p>The <code>fireOnOneErrback</code> option is particularly useful when you
706
any other results from its Deferreds).</p>
708
<p>The <code>fireOnOneErrback</code> option is particularly useful when you
365
709
want to wait for all the results if everything succeeds, but also want to know
366
immediately if something fails.</p><p>The <code>consumeErrors</code> argument will stop the DeferredList from
710
immediately if something fails.</p>
712
<p>The <code>consumeErrors</code> argument will stop the DeferredList from
367
713
propagating any errors along the callback chains of any Deferreds it contains
368
714
(usually creating a DeferredList has no effect on the results passed along the
369
715
callbacks and errbacks of their Deferreds). Stopping errors at the DeferredList
370
716
with this option will prevent <q>Unhandled error in Deferred</q> warnings from
371
the Deferreds it contains without needing to add extra errbacks<a href="#footnote-1" title="Unless of course a later callback starts a fresh error &mdash; but as we've already noted, adding callbacks to a Deferred after its used in a DeferredList is confusing and usually avoided."><super>1</super></a>.</p><a name="class"></a><h2>Class Overview<a name="auto9"></a></h2><p>This is an overview API reference for Deferred from the point of using a
717
the Deferreds it contains without needing to add extra errbacks<a href="#footnote-1" title="Unless of course a later callback starts a fresh error — but as we've already noted, adding callbacks to a Deferred after its used in a DeferredList is confusing and usually avoided."><super>1</super></a>.</p>
719
<a name="class" shape="rect"/>
721
<h2>Class Overview<a name="auto10"/></h2>
723
<p>This is an overview API reference for Deferred from the point of using a
372
724
Deferred returned by a function. It is not meant to be a
373
725
substitute for the docstrings in the Deferred class, but can provide guidelines
374
for its use.</p><p>There is a parallel overview of functions used by the Deferred's
375
<em>creator</em> in <a href="gendefer.html#class">Generating Deferreds</a>.</p><h3>Basic Callback Functions<a name="auto10"></a></h3><ul><li><code class="py-prototype">addCallbacks(self, callback[, errback, callbackArgs,
376
callbackKeywords, errbackArgs, errbackKeywords])</code><p>This is the method you will use to interact
728
<p>There is a parallel overview of functions used by the Deferred's
729
<em>creator</em> in <a href="gendefer.html#class" shape="rect">Generating Deferreds</a>.</p>
731
<h3>Basic Callback Functions<a name="auto11"/></h3>
735
<code class="py-prototype">addCallbacks(self, callback[, errback, callbackArgs,
736
callbackKeywords, errbackArgs, errbackKeywords])</code>
738
<p>This is the method you will use to interact
377
739
with Deferred. It adds a pair of callbacks <q>parallel</q> to
378
740
each other (see diagram above) in the list of callbacks
379
741
made when the Deferred is called back to. The signature of
382
744
**methodKeywords)</code>. If your method is passed in the
383
745
callback slot, for example, all arguments in the tuple
384
746
<code>callbackArgs</code> will be passed as
385
<code>*methodArgs</code> to your method.</p><p>There are various convenience methods that are
747
<code>*methodArgs</code> to your method.</p>
749
<p>There are various convenience methods that are
386
750
derivative of addCallbacks. I will not cover them in detail
387
751
here, but it is important to know about them in order to
388
create concise code.</p><ul><li><code class="py-prototype">addCallback(callback, *callbackArgs,
389
**callbackKeywords)</code><p>Adds your callback at the next point in the
752
create concise code.</p>
756
<code class="py-prototype">addCallback(callback, *callbackArgs,
757
**callbackKeywords)</code>
759
<p>Adds your callback at the next point in the
390
760
processing chain, while adding an errback that will
391
761
re-raise its first argument, not affecting further
392
processing in the error case.</p><p>Note that, while addCallbacks (plural) requires the arguments to be
762
processing in the error case.</p>
764
<p>Note that, while addCallbacks (plural) requires the arguments to be
393
765
passed in a tuple, addCallback (singular) takes all its remaining
394
766
arguments as things to be passed to the callback function. The reason is
395
767
obvious: addCallbacks (plural) cannot tell whether the arguments are
396
768
meant for the callback or the errback, so they must be specifically
397
769
marked by putting them into a tuple. addCallback (singular) knows that
398
770
everything is destined to go to the callback, so it can use Python's
399
<q>*</q> and <q>**</q> syntax to collect the remaining arguments.</p></li><li><code class="py-prototype">addErrback(errback, *errbackArgs,
400
**errbackKeywords)</code><p>Adds your errback at the next point in the
771
<q>*</q> and <q>**</q> syntax to collect the remaining arguments.</p>
776
<code class="py-prototype">addErrback(errback, *errbackArgs,
777
**errbackKeywords)</code>
779
<p>Adds your errback at the next point in the
401
780
processing chain, while adding a callback that will
402
781
return its first argument, not affecting further
403
processing in the success case.</p></li><li><code class="py-prototype">addBoth(callbackOrErrback,
782
processing in the success case.</p>
786
<code class="py-prototype">addBoth(callbackOrErrback,
404
787
*callbackOrErrbackArgs,
405
**callbackOrErrbackKeywords)</code><p>This method adds the same callback into both sides
788
**callbackOrErrbackKeywords)</code>
790
<p>This method adds the same callback into both sides
406
791
of the processing chain at both points. Keep in mind
407
792
that the type of the first argument is indeterminate if
408
793
you use this method! Use it for <code>finally:</code>
409
style blocks.</p></li></ul></li></ul><h3>Chaining Deferreds<a name="auto11"></a></h3><p>If you need one Deferred to wait on another, all you need to do is return a
801
<h3>Chaining Deferreds<a name="auto12"/></h3>
803
<p>If you need one Deferred to wait on another, all you need to do is return a
410
804
Deferred from a method added to addCallbacks. Specifically, if you return
411
805
Deferred B from a method added to Deferred A using A.addCallbacks, Deferred A's
412
806
processing chain will stop until Deferred B's .callback() method is called; at
413
807
that point, the next callback in A will be passed the result of the last
414
callback in Deferred B's processing chain at the time.</p><p>If this seems confusing, don't worry about it right now -- when you run into
808
callback in Deferred B's processing chain at the time.</p>
810
<p>If this seems confusing, don't worry about it right now -- when you run into
415
811
a situation where you need this behavior, you will probably recognize it
416
812
immediately and realize why this happens. If you want to chain deferreds
417
manually, there is also a convenience method to help you.</p><ul><li><code class="py-prototype">chainDeferred(otherDeferred)</code><p>Add <code>otherDeferred</code> to the end of this
813
manually, there is also a convenience method to help you.</p>
817
<code class="py-prototype">chainDeferred(otherDeferred)</code>
819
<p>Add <code>otherDeferred</code> to the end of this
418
820
Deferred's processing chain. When self.callback is called,
419
821
the result of my processing chain up to this point will be
420
822
passed to <code>otherDeferred.callback</code>. Further
421
823
additions to my callback chain do not affect
422
<code>otherDeferred</code></p><p>This is the same as <code class="python">self.addCallbacks(otherDeferred.callback,
423
otherDeferred.errback)</code></p></li></ul><h2>See also<a name="auto12"></a></h2><ol><li><a href="gendefer.html">Generating Deferreds</a>, an introduction to
424
writing asynchronous functions that return Deferreds.</li></ol><h2>Footnotes</h2><ol><li><a name="footnote-1"><span xmlns="http://www.w3.org/1999/xhtml" class="footnote">Unless of course a later callback starts a fresh error —
824
<code>otherDeferred</code></p>
825
<p>This is the same as <code class="python">self.addCallbacks(otherDeferred.callback,
826
otherDeferred.errback)</code></p>
830
<h2>See also<a name="auto13"/></h2>
833
<li><a href="gendefer.html" shape="rect">Generating Deferreds</a>, an introduction to
834
writing asynchronous functions that return Deferreds.</li>
837
<h2>Footnotes</h2><ol><li><a name="footnote-1"><span class="footnote">Unless of course a later callback starts a fresh error —
425
838
but as we've already noted, adding callbacks to a Deferred after its used in a
426
DeferredList is confusing and usually avoided.</span></a></li></ol></div><p><a href="index.html">Index</a></p><span class="version">Version: 8.2.0</span></body></html>
b'\\ No newline at end of file'
839
DeferredList is confusing and usually avoided.</span></a></li></ol></div>
841
<p><a href="index.html">Index</a></p>
842
<span class="version">Version: 9.0.0</span>
b'\\ No newline at end of file'