~certify-web-dev/twisted/certify-staging

« back to all changes in this revision

Viewing changes to doc/howto/defer.html

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2010-01-02 19:38:17 UTC
  • mfrom: (2.2.4 sid)
  • Revision ID: james.westby@ubuntu.com-20100102193817-jphp464ppwh7dulg
Tags: 9.0.0-1
* python-twisted: Depend on the python-twisted-* 9.0 packages.
* python-twisted: Depend on python-zope.interface only. Closes: #557781.

Show diffs side-by-side

added added

removed removed

Lines of Context:
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"?>
 
2
<!DOCTYPE html
 
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">
 
6
  <head>
 
7
<title>Twisted Documentation: Deferred Reference</title>
 
8
<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
 
9
  </head>
 
10
 
 
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>
 
14
    <div class="content">
 
15
 
 
16
<span/>
 
17
 
 
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>
 
20
 
 
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>
 
26
 
 
27
<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
10
30
return Deferreds.
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
17
 
exist.
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
 
31
</p>
 
32
 
 
33
<ul>
 
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
 
37
code.</li>
 
38
</ul>
 
39
 
 
40
<a name="deferreds" shape="rect"/>
 
41
<h2>Deferreds<a name="auto0"/></h2>
 
42
 
 
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> 
 
54
 
 
55
<h2>Callbacks<a name="auto1"/></h2>
 
56
 
 
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>
 
64
 
 
65
<pre class="python"><p class="py-linenumber"> 1
 
66
 2
 
67
 3
 
68
 4
 
69
 5
 
70
 6
 
71
 7
 
72
 8
 
73
 9
 
74
10
 
75
11
 
76
12
 
77
13
 
78
14
 
79
15
 
80
16
 
81
17
 
82
18
 
83
19
 
84
20
 
85
21
 
86
22
 
87
23
 
88
24
 
89
25
 
90
26
 
91
27
 
92
28
 
93
29
 
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>
26
95
 
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">&quot;&quot;&quot;
31
100
    hard to understand this.
32
101
    &quot;&quot;&quot;</span>
33
102
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
34
 
    <span class="py-src-comment"># simulate a delayed result by asking the reactor to fire the
35
 
</span>    <span class="py-src-comment"># Deferred in 2 seconds time with the result x * 3
36
 
</span>    <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">x</span> * <span class="py-src-number">3</span>)
 
103
    <span class="py-src-comment"># simulate a delayed result by asking the reactor to fire the</span>
 
104
    <span class="py-src-comment"># Deferred in 2 seconds time with the result x * 3</span>
 
105
    <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">x</span> * <span class="py-src-number">3</span>)
37
106
    <span class="py-src-keyword">return</span> <span class="py-src-variable">d</span>
38
107
 
39
108
<span class="py-src-keyword">def</span> <span class="py-src-identifier">printData</span>(<span class="py-src-parameter">d</span>):
46
115
<span class="py-src-variable">d</span> = <span class="py-src-variable">getDummyData</span>(<span class="py-src-number">3</span>)
47
116
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">printData</span>)
48
117
 
49
 
<span class="py-src-comment"># manually set up the end of the process by asking the reactor to
50
 
</span><span class="py-src-comment"># stop itself in 4 seconds time
51
 
</span><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>)
52
 
<span class="py-src-comment"># start up the Twisted reactor (event loop handler) manually
53
 
</span><span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
54
 
</pre><h3>Multiple callbacks<a name="auto1"></a></h3><p>Multiple callbacks can be added to a Deferred.  The first callback in the
 
118
<span class="py-src-comment"># manually set up the end of the process by asking the reactor to</span>
 
119
<span class="py-src-comment"># stop itself in 4 seconds time</span>
 
120
<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>)
 
121
<span class="py-src-comment"># start up the Twisted reactor (event loop handler) manually</span>
 
122
<span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
 
123
</pre>
 
124
 
 
125
<h3>Multiple callbacks<a name="auto2"/></h3>
 
126
 
 
127
<p>Multiple callbacks can be added to a Deferred.  The first callback in the
55
128
Deferred's callback chain will be called with the result, the second with the
56
129
result of the first callback, and so on. Why do we need this?  Well, consider
57
130
a Deferred returned by twisted.enterprise.adbapi - the result of a SQL query.
58
131
A web widget might add a callback that converts this result into HTML, and
59
132
pass the Deferred onwards, where the callback will be used by twisted to
60
133
return the result to the HTTP client. The callback chain will be bypassed in
61
 
case of errors or exceptions.</p><pre class="python">
62
 
<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>
 
134
case of errors or exceptions.</p>
 
135
 
 
136
<pre class="python"><p class="py-linenumber"> 1
 
137
 2
 
138
 3
 
139
 4
 
140
 5
 
141
 6
 
142
 7
 
143
 8
 
144
 9
 
145
10
 
146
11
 
147
12
 
148
13
 
149
14
 
150
15
 
151
16
 
152
17
 
153
18
 
154
19
 
155
20
 
156
21
 
157
22
 
158
23
 
159
24
 
160
25
 
161
26
 
162
27
 
163
28
 
164
29
 
165
30
 
166
31
 
167
32
 
168
33
 
169
34
 
170
35
 
171
36
 
172
37
 
173
38
 
174
39
 
175
40
 
176
41
 
177
42
 
178
43
 
179
44
 
180
45
 
181
46
 
182
47
 
183
48
 
184
49
 
185
50
 
186
51
 
187
52
 
188
53
 
189
54
 
190
55
 
191
56
 
192
57
 
193
58
 
194
59
 
195
60
 
196
61
 
197
62
 
198
63
 
199
64
 
200
</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>
63
201
 
64
202
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Getter</span>:
65
203
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">gotResults</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">x</span>):
97
235
        setup.
98
236
        &quot;&quot;&quot;</span>
99
237
        <span class="py-src-variable">self</span>.<span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
100
 
        <span class="py-src-comment"># simulate a delayed result by asking the reactor to schedule
101
 
</span>        <span class="py-src-comment"># gotResults in 2 seconds time
102
 
</span>        <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">self</span>.<span class="py-src-variable">gotResults</span>, <span class="py-src-variable">x</span>)
 
238
        <span class="py-src-comment"># simulate a delayed result by asking the reactor to schedule</span>
 
239
        <span class="py-src-comment"># gotResults in 2 seconds time</span>
 
240
        <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">self</span>.<span class="py-src-variable">gotResults</span>, <span class="py-src-variable">x</span>)
103
241
        <span class="py-src-variable">self</span>.<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">self</span>.<span class="py-src-variable">_toHTML</span>)
104
242
        <span class="py-src-keyword">return</span> <span class="py-src-variable">self</span>.<span class="py-src-variable">d</span>
105
243
 
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>))
112
250
 
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>)
118
256
 
119
 
<span class="py-src-comment"># this series of callbacks and errbacks will print &quot;Result: 12&quot;
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 &quot;Result: 12&quot;</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>)
124
262
 
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
 
264
</pre>
 
265
 
 
266
<h3>Visual Explanation<a name="auto3"/></h3>
 
267
 
 
268
<div align="center" hlint="off">
 
269
<img src="../img/deferred-attach.png"/>
 
270
</div>
 
271
 
 
272
<ol>
 
273
  <li>Requesting method (data sink) requests data, gets
 
274
  Deferred object.</li>
 
275
  
 
276
  <li>Requesting method attaches callbacks to Deferred
 
277
  object.</li>
 
278
</ol>
 
279
<img align="left" hlint="off" src="../img/deferred-process.png"/> 
 
280
 
 
281
<ol>
 
282
  
 
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>
 
287
  instance.</li>
 
288
  
 
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. 
136
293
  
137
 
  <ul><li>Result of the callback is always passed as the first
 
294
  <ul>
 
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
 
297
    processors.</li>
 
298
    
 
299
    <li>If a callback raises an exception, switch to
 
300
    errback.</li>
 
301
    
 
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
 
305
    statements.</li>
 
306
    
 
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>
 
310
  </ul> </li>
 
311
</ol>
 
312
<br clear="all" hlint="off"/>
 
313
 
 
314
<h2>Errbacks<a name="auto4"/></h2>
 
315
 
 
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>
 
319
 
 
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>
 
325
 
 
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>
 
333
 
 
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>
 
339
 
 
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>()
 
342
of:</p>
 
343
 
 
344
<pre class="python"><p class="py-linenumber">1
 
345
2
 
346
3
 
347
4
 
348
5
 
349
6
 
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
169
 
</span>    ...
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>
 
355
    ...
 
356
</pre>
 
357
 
 
358
<p>You do this by:</p>
 
359
<pre class="python"><p class="py-linenumber">1
 
360
2
 
361
3
 
362
4
 
363
5
 
364
6
 
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
174
 
</span>
 
367
    <span class="py-src-comment"># Handle SpamExceptions and EggExceptions</span>
 
368
 
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>
 
371
</pre>
 
372
 
 
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>
 
376
 
 
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>
 
380
 
 
381
<pre class="python"><p class="py-linenumber"> 1
 
382
 2
 
383
 3
 
384
 4
 
385
 5
 
386
 6
 
387
 7
 
388
 8
 
389
 9
 
390
10
 
391
11
 
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>)        
188
398
 
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
 
403
</pre>
 
404
 
 
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, &quot;A&quot; will
 
408
callbacks and errbacks.</p>
 
409
 
 
410
<p>What this means in a practical sense is in Case 1, &quot;A&quot; will
197
411
handle a success condition from <code>getDeferredFromSomewhere</code>, and
198
412
&quot;B&quot; will handle any errors that occur <em>from either the upstream
199
413
source, or that occur in 'A'</em>.  In Case 2, &quot;C&quot;'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>
 
417
 
 
418
 
 
419
<h3>Unhandled Errors<a name="auto5"/></h3>
 
420
 
 
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>
 
429
 
 
430
<pre class="python"><p class="py-linenumber">1
 
431
2
 
432
3
 
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>
 
436
</pre>
 
437
 
 
438
<h2>Handling either synchronous or asynchronous results<a name="auto6"/></h2>
 
439
<p>
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
219
445
when that data arrives. However, a function that wants to check if a user is
220
446
authenticated will then need to accept both immediate results <em> and</em>
221
447
Deferreds.
222
 
</p><p>
 
448
</p>
 
449
 
 
450
<p>
223
451
In this example, the library function <code>authenticateUser</code> uses the
224
452
application function <code>isValidUser</code> to authenticate a user:
225
 
</p><pre class="python">
226
 
<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>):
 
453
</p>
 
454
 
 
455
<pre class="python"><p class="py-linenumber">1
 
456
2
 
457
3
 
458
4
 
459
5
 
460
</p><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>):
227
461
    <span class="py-src-keyword">if</span> <span class="py-src-variable">isValidUser</span>(<span class="py-src-variable">user</span>):
228
462
        <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;User is authenticated&quot;</span>
229
463
    <span class="py-src-keyword">else</span>:
230
464
        <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;User is not authenticated&quot;</span>
231
 
</pre><p>
 
465
</pre>
 
466
 
 
467
<p>
232
468
However, it assumes that <code>isValidUser</code> returns immediately,
233
469
whereas <code>isValidUser</code> may actually authenticate the user
234
470
asynchronously and return a Deferred. It is possible to adapt this
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>
 
479
</p>
 
480
 
 
481
<h3>Handling possible Deferreds in the library code<a name="auto7"/></h3>
 
482
 
 
483
<p>
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>):
 
486
</p>
 
487
 
 
488
<div class="py-listing"><pre><p class="py-linenumber">1
 
489
2
 
490
3
 
491
4
 
492
5
 
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
250
496
    '''</span>
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">&quot;Alice&quot;</span>, <span class="py-src-string">&quot;Angus&quot;</span>, <span class="py-src-string">&quot;Agnes&quot;</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>
 
499
 
 
500
<p>
253
501
However, here's an <code>asynchronousIsValidUser</code> function that returns
254
502
a Deferred:
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>
 
503
</p>
 
504
 
 
505
<pre class="python"><p class="py-linenumber">1
 
506
2
 
507
3
 
508
4
 
509
5
 
510
6
 
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>
257
512
 
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">&quot;Alice&quot;</span>, <span class="py-src-string">&quot;Angus&quot;</span>, <span class="py-src-string">&quot;Agnes&quot;</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
 
517
</pre>
 
518
 
 
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>
 
525
</p>
 
526
 
 
527
<pre class="python"><p class="py-linenumber"> 1
 
528
 2
 
529
 3
 
530
 4
 
531
 5
 
532
 6
 
533
 7
 
534
 8
 
535
 9
 
536
10
 
537
11
 
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>
270
539
 
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>)
280
 
</pre><p>
 
549
</pre>
 
550
 
 
551
<p>
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
 
554
</p>
 
555
 
 
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
 
558
information.</p>
 
559
 
 
560
<h2>DeferredList<a name="auto8"/></h2>
 
561
 
 
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
 
565
this.</p>
 
566
 
 
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
 
570
2
 
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>])
 
573
</pre>
 
574
 
 
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>
 
579
 
 
580
<pre class="python"><p class="py-linenumber"> 1
 
581
 2
 
582
 3
 
583
 4
 
584
 5
 
585
 6
 
586
 7
 
587
 8
 
588
 9
 
589
10
 
590
11
 
591
12
 
592
13
 
593
14
 
594
15
 
595
16
 
596
17
 
597
18
 
598
19
 
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>
 
618
</pre>
 
619
 
 
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>
 
624
 
 
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>
 
633
 
 
634
 
 
635
 
 
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>
 
640
</div>
 
641
 
 
642
<pre class="python"><p class="py-linenumber"> 1
 
643
 2
 
644
 3
 
645
 4
 
646
 5
 
647
 6
 
648
 7
 
649
 8
 
650
 9
 
651
10
 
652
11
 
653
12
 
654
13
 
655
14
 
656
15
 
657
16
 
658
17
 
659
18
 
660
19
 
661
20
 
662
21
 
663
22
 
664
23
 
665
24
 
666
25
 
667
26
 
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">&quot; ten&quot;</span>
334
672
 
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">&quot;one&quot;</span>) <span class="py-src-comment"># fires addTen, checks DeferredList, stores &quot;one ten&quot;</span>
342
680
<span class="py-src-variable">deferred2</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;two&quot;</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')]
345
 
</span>
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>
 
683
 
 
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">&quot;one&quot;</span>) <span class="py-src-comment"># checks DeferredList, stores &quot;one&quot;, fires addTen</span>
353
691
<span class="py-src-variable">deferred2</span>.<span class="py-src-variable">callback</span>(<span class="py-src-string">&quot;two&quot;</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>
 
694
</pre>
 
695
 
 
696
<h3>Other behaviours<a name="auto9"/></h3>
 
697
 
 
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>
 
707
 
 
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>
 
711
 
 
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 &amp;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>
 
718
 
 
719
<a name="class" shape="rect"/>
 
720
 
 
721
<h2>Class Overview<a name="auto10"/></h2>
 
722
 
 
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
 
726
for its use.</p>
 
727
 
 
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>
 
730
 
 
731
<h3>Basic Callback Functions<a name="auto11"/></h3>
 
732
 
 
733
<ul>
 
734
  <li>
 
735
  <code class="py-prototype">addCallbacks(self, callback[, errback, callbackArgs,
 
736
  callbackKeywords, errbackArgs, errbackKeywords])</code> 
 
737
  
 
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>
 
748
  
 
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>
 
753
  
 
754
  <ul>
 
755
    <li>
 
756
    <code class="py-prototype">addCallback(callback, *callbackArgs,
 
757
    **callbackKeywords)</code> 
 
758
    
 
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>
 
763
 
 
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>
 
772
    
 
773
    </li>
 
774
    
 
775
    <li>
 
776
    <code class="py-prototype">addErrback(errback, *errbackArgs,
 
777
    **errbackKeywords)</code> 
 
778
    
 
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>
 
783
    </li>
 
784
    
 
785
    <li>
 
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> 
 
789
    
 
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
 
794
    style blocks.</p>
 
795
    </li>
 
796
  </ul> </li>
 
797
  
 
798
</ul>
 
799
 
 
800
 
 
801
<h3>Chaining Deferreds<a name="auto12"/></h3>
 
802
 
 
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>
 
809
 
 
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>
 
814
 
 
815
<ul>
 
816
  <li>
 
817
  <code class="py-prototype">chainDeferred(otherDeferred)</code> 
 
818
  
 
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 &mdash;
 
824
  <code>otherDeferred</code></p>
 
825
  <p>This is the same as <code class="python">self.addCallbacks(otherDeferred.callback,
 
826
  otherDeferred.errback)</code></p>
 
827
  </li>
 
828
</ul>
 
829
    
 
830
<h2>See also<a name="auto13"/></h2>
 
831
 
 
832
<ol>
 
833
<li><a href="gendefer.html" shape="rect">Generating Deferreds</a>, an introduction to
 
834
writing asynchronous functions that return Deferreds.</li>
 
835
</ol>
 
836
 
 
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>
 
840
 
 
841
    <p><a href="index.html">Index</a></p>
 
842
    <span class="version">Version: 9.0.0</span>
 
843
  </body>
 
844
</html>
 
 
b'\\ No newline at end of file'