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

« back to all changes in this revision

Viewing changes to doc/howto/deferredindepth.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: Deferreds are beautiful! (A Tutorial)</title><link href="stylesheet.css" type="text/css" rel="stylesheet" /></head><body bgcolor="white"><h1 class="title">Deferreds are beautiful! (A Tutorial)</h1><div class="toc"><ol><li><a href="#auto0">Introduction</a></li><li><a href="#auto1">A simple example</a></li><li><a href="#auto2">Errbacks</a></li><ul><li><a href="#auto3">Failure in requested operation</a></li><li><a href="#auto4">Exceptions raised in callbacks</a></li><li><a href="#auto5">Exceptions will only be handled by errbacks</a></li><li><a href="#auto6">Handling an exception and continuing on</a></li></ul><li><a href="#auto7">addBoth: the deferred version of finally</a></li><li><a href="#auto8">addCallbacks: decision making based on previous success or failure</a></li><li><a href="#auto9">Hints, tips, common mistakes, and miscellaney</a></li><ul><li><a href="#auto10">The deferred callback chain is stateful</a></li><li><a href="#auto11">Don't call .callback() on deferreds you didn't create!</a></li><li><a href="#auto12">Callbacks can return deferreds</a></li></ul><li><a href="#auto13">Conclusion</a></li></ol></div><div class="content"><span></span><h2>Introduction<a name="auto0"></a></h2><p>Deferreds are quite possibly the single most confusing topic that a
 
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: Deferreds are beautiful! (A Tutorial)</title>
 
8
<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
 
9
  </head>
 
10
 
 
11
  <body bgcolor="white">
 
12
    <h1 class="title">Deferreds are beautiful! (A Tutorial)</h1>
 
13
    <div class="toc"><ol><li><a href="#auto0">Introduction</a></li><li><a href="#auto1">A simple example</a></li><li><a href="#auto2">Errbacks</a></li><ul><li><a href="#auto3">Failure in requested operation</a></li><li><a href="#auto4">Exceptions raised in callbacks</a></li><li><a href="#auto5">Exceptions will only be handled by errbacks</a></li><li><a href="#auto6">Handling an exception and continuing on</a></li></ul><li><a href="#auto7">addBoth: the deferred version of finally</a></li><li><a href="#auto8">addCallbacks: decision making based on previous success or failure</a></li><li><a href="#auto9">Hints, tips, common mistakes, and miscellaney</a></li><ul><li><a href="#auto10">The deferred callback chain is stateful</a></li><li><a href="#auto11">Don't call .callback() on deferreds you didn't create!</a></li><li><a href="#auto12">Callbacks can return deferreds</a></li></ul><li><a href="#auto13">Conclusion</a></li></ol></div>
 
14
    <div class="content">
 
15
<span/>
 
16
 
 
17
<h2>Introduction<a name="auto0"/></h2>
 
18
 
 
19
<p>Deferreds are quite possibly the single most confusing topic that a
3
20
newcomer to Twisted has to deal with. I am going to forgo the normal talk
4
21
about what deferreds are, what they aren't, and why they're used in Twisted.
5
22
Instead, I'm going show you the logic behind what they
6
 
<strong>do</strong>.</p><p>A deferred allows you to encapsulate the logic that you'd normally use to
 
23
<strong>do</strong>.</p>
 
24
 
 
25
 
 
26
<p>A deferred allows you to encapsulate the logic that you'd normally use to
7
27
make a series of function calls after receiving a result into a single object.
8
28
In the examples that follow, I'll first show you what's going to go on behind 
9
29
the scenes in the deferred chain, then show you the deferred API calls that set
10
30
up that chain. All of these examples are runnable code, so feel free to play 
11
 
around with them.</p><h2>A simple example<a name="auto1"></a></h2>
 
31
around with them.</p>
 
32
 
 
33
 
 
34
<h2>A simple example<a name="auto1"/></h2>
12
35
 
13
36
First, a simple example so that we have something to talk about:
14
37
 
15
 
<div class="py-listing"><pre>
16
 
<span class="py-src-comment">#!/usr/bin/python
17
 
</span>
 
38
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
39
 2
 
40
 3
 
41
 4
 
42
 5
 
43
 6
 
44
 7
 
45
 8
 
46
 9
 
47
10
 
48
11
 
49
12
 
50
13
 
51
14
 
52
15
 
53
16
 
54
17
 
55
18
 
56
19
 
57
20
 
58
21
 
59
22
 
60
23
 
61
24
 
62
25
 
63
26
 
64
27
 
65
28
 
66
29
 
67
30
 
68
31
 
69
32
 
70
33
 
71
34
 
72
35
 
73
36
 
74
37
 
75
38
 
76
39
 
77
40
 
78
41
 
79
42
 
80
43
 
81
44
 
82
45
 
83
46
 
84
47
 
85
48
 
86
49
 
87
50
 
88
51
 
89
52
 
90
53
 
91
54
 
92
55
 
93
56
 
94
57
 
95
58
 
96
59
 
97
60
 
98
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
99
 
 
100
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
101
<span class="py-src-comment"># See LICENSE for details.</span>
 
102
 
18
103
<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>
19
104
<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">failure</span>, <span class="py-src-variable">util</span>
20
105
 
21
106
<span class="py-src-string">&quot;&quot;&quot;
22
 
here we have the simplest case, a single callback and a single errback
 
107
Here we have the simplest case, a single callback and a single errback.
23
108
&quot;&quot;&quot;</span>
24
109
 
25
110
<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
37
122
 
38
123
 
39
124
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
40
 
    <span class="py-src-comment"># equivalent to d.callback(result)
41
 
</span>
 
125
    <span class="py-src-comment"># equivalent to d.callback(result)</span>
 
126
 
42
127
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
43
128
        <span class="py-src-keyword">try</span>:
44
129
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
70
155
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
71
156
    <span class="py-src-keyword">global</span> <span class="py-src-variable">num</span>; <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
72
157
    <span class="py-src-variable">deferredExample</span>()
73
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex.py"><span class="filename">listings/deferred/deferred_ex.py</span></a></div></div><p>And the output: (since both methods in the example produce the same output,
74
 
it will only be shown once.) </p><pre>
 
158
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex.py"><span class="filename">listings/deferred/deferred_ex.py</span></a></div></div>
 
159
 
 
160
<p>And the output: (since both methods in the example produce the same output,
 
161
it will only be shown once.) </p>
 
162
 
 
163
<pre xml:space="preserve">
75
164
callback 1
76
165
        got result: success
77
 
</pre><p>Here we have the simplest case. A deferred with a single callback and a
 
166
</pre>
 
167
 
 
168
<p>Here we have the simplest case. A deferred with a single callback and a
78
169
single errback. Normally, a function would create a deferred and hand it back
79
170
to you when you request an operation that needs to wait for an event for
80
171
completion.  The object you called then does <code>d.callback(result)</code>
81
172
when the results are in.  
82
 
</p><p>The thing to notice is that there is only one result that is passed from
 
173
</p>
 
174
 
 
175
<p>The thing to notice is that there is only one result that is passed from
83
176
method to method, and that the result returned from a method is the argument
84
177
to the next method in the chain. In case of an exception, result is set to an
85
 
instance of <code class="API"><a href="http://twistedmatrix.com/documents/8.2.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">Failure</a></code>
86
 
that describes the exception.</p><h2>Errbacks<a name="auto2"></a></h2><h3>Failure in requested operation<a name="auto3"></a></h3><p>Things don't always go as planned, and sometimes the function that
 
178
instance of <code class="API"><a href="http://twistedmatrix.com/documents/9.0.0/api/twisted.python.failure.Failure.html" title="twisted.python.failure.Failure">Failure</a></code>
 
179
that describes the exception.</p>
 
180
 
 
181
<h2>Errbacks<a name="auto2"/></h2>
 
182
<h3>Failure in requested operation<a name="auto3"/></h3>
 
183
<p>Things don't always go as planned, and sometimes the function that
87
184
returned the deferred needs to alert the callback chain that an error
88
 
has occurred.</p><div class="py-listing"><pre>
89
 
<span class="py-src-comment">#!/usr/bin/python
90
 
</span>
 
185
has occurred.</p>
 
186
 
 
187
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
188
 2
 
189
 3
 
190
 4
 
191
 5
 
192
 6
 
193
 7
 
194
 8
 
195
 9
 
196
10
 
197
11
 
198
12
 
199
13
 
200
14
 
201
15
 
202
16
 
203
17
 
204
18
 
205
19
 
206
20
 
207
21
 
208
22
 
209
23
 
210
24
 
211
25
 
212
26
 
213
27
 
214
28
 
215
29
 
216
30
 
217
31
 
218
32
 
219
33
 
220
34
 
221
35
 
222
36
 
223
37
 
224
38
 
225
39
 
226
40
 
227
41
 
228
42
 
229
43
 
230
44
 
231
45
 
232
46
 
233
47
 
234
48
 
235
49
 
236
50
 
237
51
 
238
52
 
239
53
 
240
54
 
241
55
 
242
56
 
243
57
 
244
58
 
245
59
 
246
60
 
247
61
 
248
62
 
249
63
 
250
64
 
251
65
 
252
66
 
253
67
 
254
68
 
255
69
 
256
70
 
257
71
 
258
72
 
259
73
 
260
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
261
 
 
262
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
263
<span class="py-src-comment"># See LICENSE for details.</span>
 
264
 
91
265
<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>
92
266
<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">failure</span>, <span class="py-src-variable">util</span>
93
267
 
94
268
<span class="py-src-string">&quot;&quot;&quot;
95
 
this example is analogous to a function calling .errback(failure)
 
269
This example is analogous to a function calling .errback(failure)
96
270
&quot;&quot;&quot;</span>
97
271
 
98
272
 
156
330
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
157
331
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
158
332
    <span class="py-src-variable">deferredExample</span>(<span class="py-src-variable">result</span>)
159
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex1a.py"><span class="filename">listings/deferred/deferred_ex1a.py</span></a></div></div><pre>
 
333
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex1a.py"><span class="filename">listings/deferred/deferred_ex1a.py</span></a></div></div>
 
334
 
 
335
<pre xml:space="preserve">
160
336
errback
161
337
we got an exception: Traceback (most recent call last):
162
338
--- exception caught here ---
163
339
  File &quot;deferred_ex1a.py&quot;, line 73, in ?
164
340
    raise RuntimeError, &quot;*doh*! failure!&quot;
165
341
exceptions.RuntimeError: *doh*! failure!
166
 
</pre><p> The important thing to note (as it will come up again in later examples)
 
342
</pre>
 
343
 
 
344
<p> The important thing to note (as it will come up again in later examples)
167
345
is that the callback isn't touched, the failure goes right to the errback.
168
346
Also note that the errback trap()s the expected exception type. If you don't
169
347
trap the exception, an error will be logged when the deferred is
170
348
garbage-collected. 
171
 
</p><h3>Exceptions raised in callbacks<a name="auto4"></a></h3><p>Now let's see what happens when <em>our callback</em> raises an
172
 
exception</p><div class="py-listing"><pre>
173
 
<span class="py-src-comment">#!/usr/bin/python
174
 
</span>
 
349
</p>
 
350
 
 
351
 
 
352
<h3>Exceptions raised in callbacks<a name="auto4"/></h3>
 
353
 
 
354
<p>Now let's see what happens when <em>our callback</em> raises an
 
355
exception</p>
 
356
 
 
357
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
358
 2
 
359
 3
 
360
 4
 
361
 5
 
362
 6
 
363
 7
 
364
 8
 
365
 9
 
366
10
 
367
11
 
368
12
 
369
13
 
370
14
 
371
15
 
372
16
 
373
17
 
374
18
 
375
19
 
376
20
 
377
21
 
378
22
 
379
23
 
380
24
 
381
25
 
382
26
 
383
27
 
384
28
 
385
29
 
386
30
 
387
31
 
388
32
 
389
33
 
390
34
 
391
35
 
392
36
 
393
37
 
394
38
 
395
39
 
396
40
 
397
41
 
398
42
 
399
43
 
400
44
 
401
45
 
402
46
 
403
47
 
404
48
 
405
49
 
406
50
 
407
51
 
408
52
 
409
53
 
410
54
 
411
55
 
412
56
 
413
57
 
414
58
 
415
59
 
416
60
 
417
61
 
418
62
 
419
63
 
420
64
 
421
65
 
422
66
 
423
67
 
424
68
 
425
69
 
426
70
 
427
71
 
428
72
 
429
73
 
430
74
 
431
75
 
432
76
 
433
77
 
434
78
 
435
79
 
436
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
437
 
 
438
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
439
<span class="py-src-comment"># See LICENSE for details.</span>
 
440
 
175
441
<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>
176
442
<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">failure</span>, <span class="py-src-variable">util</span>
177
443
 
178
444
<span class="py-src-string">&quot;&quot;&quot;
179
 
here we have a slightly more involved case. The deferred is called back with a
 
445
Here we have a slightly more involved case. The deferred is called back with a
180
446
result. the first callback returns a value, the second callback, however
181
447
raises an exception, which is handled by the errback.
182
448
&quot;&quot;&quot;</span>
246
512
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
247
513
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
248
514
    <span class="py-src-variable">deferredExample</span>()
249
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex1b.py"><span class="filename">listings/deferred/deferred_ex1b.py</span></a></div></div><p>And the output: (note, tracebacks will be edited slightly to conserve
250
 
space)</p><pre>
 
515
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex1b.py"><span class="filename">listings/deferred/deferred_ex1b.py</span></a></div></div>
 
516
 
 
517
<p>And the output: (note, tracebacks will be edited slightly to conserve
 
518
space)</p>
 
519
 
 
520
<pre xml:space="preserve">
251
521
callback 1
252
522
        got result: success
253
523
callback 2
262
532
  File &quot;./deferred_ex1.py&quot;, line 32, in failAtHandlingResult
263
533
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
264
534
exceptions.RuntimeError: whoops! we encountered an error
265
 
</pre><p>If your callback raises an exception, the next method to be called will be 
266
 
the next errback in your chain.</p><h3>Exceptions will only be handled by errbacks<a name="auto5"></a></h3><p>If a callback raises an exception the next method to be called will be next
 
535
</pre>
 
536
 
 
537
<p>If your callback raises an exception, the next method to be called will be 
 
538
the next errback in your chain.</p>
 
539
 
 
540
 
 
541
<h3>Exceptions will only be handled by errbacks<a name="auto5"/></h3>
 
542
 
 
543
<p>If a callback raises an exception the next method to be called will be next
267
544
errback in the chain. If the chain is started off with a failure, the first
268
 
method to be called will be the first errback.</p><div class="py-listing"><pre>
269
 
<span class="py-src-comment">#!/usr/bin/python
270
 
</span>
 
545
method to be called will be the first errback.</p>
 
546
 
 
547
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
548
 2
 
549
 3
 
550
 4
 
551
 5
 
552
 6
 
553
 7
 
554
 8
 
555
 9
 
556
10
 
557
11
 
558
12
 
559
13
 
560
14
 
561
15
 
562
16
 
563
17
 
564
18
 
565
19
 
566
20
 
567
21
 
568
22
 
569
23
 
570
24
 
571
25
 
572
26
 
573
27
 
574
28
 
575
29
 
576
30
 
577
31
 
578
32
 
579
33
 
580
34
 
581
35
 
582
36
 
583
37
 
584
38
 
585
39
 
586
40
 
587
41
 
588
42
 
589
43
 
590
44
 
591
45
 
592
46
 
593
47
 
594
48
 
595
49
 
596
50
 
597
51
 
598
52
 
599
53
 
600
54
 
601
55
 
602
56
 
603
57
 
604
58
 
605
59
 
606
60
 
607
61
 
608
62
 
609
63
 
610
64
 
611
65
 
612
66
 
613
67
 
614
68
 
615
69
 
616
70
 
617
71
 
618
72
 
619
73
 
620
74
 
621
75
 
622
76
 
623
77
 
624
78
 
625
79
 
626
80
 
627
81
 
628
82
 
629
83
 
630
84
 
631
85
 
632
86
 
633
87
 
634
88
 
635
89
 
636
90
 
637
91
 
638
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
639
 
 
640
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
641
<span class="py-src-comment"># See LICENSE for details.</span>
 
642
 
271
643
<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>
272
644
<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">failure</span>, <span class="py-src-variable">util</span>
273
645
 
274
646
<span class="py-src-string">&quot;&quot;&quot;
275
 
this example shows an important concept that many deferred newbies
 
647
This example shows an important concept that many deferred newbies
276
648
(myself included) have trouble understanding.
277
649
 
278
650
when an error occurs in a callback, the first errback after the error
279
651
occurs will be the next method called. (in the next example we'll
280
 
see what happens in the 'chain' after an errback)
281
 
 
 
652
see what happens in the 'chain' after an errback).
282
653
&quot;&quot;&quot;</span>
283
654
 
284
655
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
305
676
 
306
677
 
307
678
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
308
 
    <span class="py-src-comment"># equivalent to d.callback(result)
309
 
</span>
310
 
    <span class="py-src-comment"># now, let's make the error happen in the first callback
311
 
</span>
 
679
    <span class="py-src-comment"># equivalent to d.callback(result)</span>
 
680
 
 
681
    <span class="py-src-comment"># now, let's make the error happen in the first callback</span>
 
682
 
312
683
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
313
684
        <span class="py-src-keyword">try</span>:
314
685
            <span class="py-src-variable">result</span> = <span class="py-src-variable">failAtHandlingResult</span>(<span class="py-src-variable">result</span>)
318
689
        <span class="py-src-keyword">pass</span>
319
690
 
320
691
 
321
 
    <span class="py-src-comment"># note: this callback will be skipped because
322
 
</span>    <span class="py-src-comment"># result is a failure
323
 
</span>
 
692
    <span class="py-src-comment"># note: this callback will be skipped because</span>
 
693
    <span class="py-src-comment"># result is a failure</span>
 
694
 
324
695
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
325
696
        <span class="py-src-keyword">try</span>:
326
697
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
354
725
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
355
726
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
356
727
    <span class="py-src-variable">deferredExample</span>()
357
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex2.py"><span class="filename">listings/deferred/deferred_ex2.py</span></a></div></div><pre>
 
728
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex2.py"><span class="filename">listings/deferred/deferred_ex2.py</span></a></div></div>
 
729
 
 
730
<pre xml:space="preserve">
358
731
callback 1
359
732
        got result: success
360
733
        about to raise exception
368
741
  File &quot;./deferred_ex2.py&quot;, line 35, in failAtHandlingResult
369
742
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
370
743
exceptions.RuntimeError: whoops! we encountered an error
371
 
</pre><p>You can see that our second callback, handleResult was not called because
372
 
failAtHandlingResult raised an exception</p><h3>Handling an exception and continuing on<a name="auto6"></a></h3><p>In this example, we see an errback handle an exception raised in the
 
744
</pre>
 
745
 
 
746
<p>You can see that our second callback, handleResult was not called because
 
747
failAtHandlingResult raised an exception</p>
 
748
 
 
749
<h3>Handling an exception and continuing on<a name="auto6"/></h3>
 
750
 
 
751
<p>In this example, we see an errback handle an exception raised in the
373
752
preceeding callback.  Take note that it could just as easily been an exception
374
753
from <strong>any other</strong> preceeding method. You'll see that after the
375
754
exception is handled in the errback (i.e.  the errback does not return a
376
755
failure or raise an exception) the chain continues on with the next
377
 
callback.</p><div class="py-listing"><pre>
378
 
<span class="py-src-comment">#!/usr/bin/python
379
 
</span>
 
756
callback.</p>
 
757
 
 
758
<div class="py-listing"><pre><p class="py-linenumber">  1
 
759
  2
 
760
  3
 
761
  4
 
762
  5
 
763
  6
 
764
  7
 
765
  8
 
766
  9
 
767
 10
 
768
 11
 
769
 12
 
770
 13
 
771
 14
 
772
 15
 
773
 16
 
774
 17
 
775
 18
 
776
 19
 
777
 20
 
778
 21
 
779
 22
 
780
 23
 
781
 24
 
782
 25
 
783
 26
 
784
 27
 
785
 28
 
786
 29
 
787
 30
 
788
 31
 
789
 32
 
790
 33
 
791
 34
 
792
 35
 
793
 36
 
794
 37
 
795
 38
 
796
 39
 
797
 40
 
798
 41
 
799
 42
 
800
 43
 
801
 44
 
802
 45
 
803
 46
 
804
 47
 
805
 48
 
806
 49
 
807
 50
 
808
 51
 
809
 52
 
810
 53
 
811
 54
 
812
 55
 
813
 56
 
814
 57
 
815
 58
 
816
 59
 
817
 60
 
818
 61
 
819
 62
 
820
 63
 
821
 64
 
822
 65
 
823
 66
 
824
 67
 
825
 68
 
826
 69
 
827
 70
 
828
 71
 
829
 72
 
830
 73
 
831
 74
 
832
 75
 
833
 76
 
834
 77
 
835
 78
 
836
 79
 
837
 80
 
838
 81
 
839
 82
 
840
 83
 
841
 84
 
842
 85
 
843
 86
 
844
 87
 
845
 88
 
846
 89
 
847
 90
 
848
 91
 
849
 92
 
850
 93
 
851
 94
 
852
 95
 
853
 96
 
854
 97
 
855
 98
 
856
 99
 
857
100
 
858
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
859
 
 
860
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
861
<span class="py-src-comment"># See LICENSE for details.</span>
 
862
 
380
863
<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>
381
864
<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">failure</span>, <span class="py-src-variable">util</span>
382
865
 
383
866
<span class="py-src-string">&quot;&quot;&quot;
384
 
now we see how an errback can handle errors. if an errback
 
867
Now we see how an errback can handle errors. if an errback
385
868
does not raise an exception, the next callback in the chain
386
 
will be called
387
 
 
 
869
will be called.
388
870
&quot;&quot;&quot;</span>
389
871
 
390
872
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
418
900
 
419
901
 
420
902
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
421
 
    <span class="py-src-comment"># equivalent to d.callback(result)
422
 
</span>
 
903
    <span class="py-src-comment"># equivalent to d.callback(result)</span>
 
904
 
423
905
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
424
906
        <span class="py-src-keyword">try</span>:
425
907
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
472
954
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
473
955
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
474
956
    <span class="py-src-variable">deferredExample</span>()
475
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex3.py"><span class="filename">listings/deferred/deferred_ex3.py</span></a></div></div><pre>
 
957
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex3.py"><span class="filename">listings/deferred/deferred_ex3.py</span></a></div></div>
 
958
 
 
959
<pre xml:space="preserve">
476
960
callback 1
477
961
        got result: success
478
962
callback 2
497
981
 
498
982
callback 3
499
983
        got result: okay, continue on
500
 
</pre><h2>addBoth: the deferred version of <em>finally</em><a name="auto7"></a></h2><p>Now we see how deferreds do <strong>finally</strong>, with .addBoth. The
 
984
</pre>
 
985
 
 
986
<h2>addBoth: the deferred version of <em>finally</em><a name="auto7"/></h2>
 
987
 
 
988
<p>Now we see how deferreds do <strong>finally</strong>, with .addBoth. The
501
989
callback that gets added as addBoth will be called if the result is a failure
502
990
or non-failure. We'll also see in this example, that our doThisNoMatterWhat()
503
991
method follows a common idiom in deferred callbacks by acting as a passthru,
504
992
returning the value that it received to allow processing the chain to
505
 
continue, but appearing transparent in terms of the result.</p><div class="py-listing"><pre>
506
 
<span class="py-src-comment">#!/usr/bin/python
507
 
</span>
 
993
continue, but appearing transparent in terms of the result.</p>
 
994
 
 
995
<div class="py-listing"><pre><p class="py-linenumber">  1
 
996
  2
 
997
  3
 
998
  4
 
999
  5
 
1000
  6
 
1001
  7
 
1002
  8
 
1003
  9
 
1004
 10
 
1005
 11
 
1006
 12
 
1007
 13
 
1008
 14
 
1009
 15
 
1010
 16
 
1011
 17
 
1012
 18
 
1013
 19
 
1014
 20
 
1015
 21
 
1016
 22
 
1017
 23
 
1018
 24
 
1019
 25
 
1020
 26
 
1021
 27
 
1022
 28
 
1023
 29
 
1024
 30
 
1025
 31
 
1026
 32
 
1027
 33
 
1028
 34
 
1029
 35
 
1030
 36
 
1031
 37
 
1032
 38
 
1033
 39
 
1034
 40
 
1035
 41
 
1036
 42
 
1037
 43
 
1038
 44
 
1039
 45
 
1040
 46
 
1041
 47
 
1042
 48
 
1043
 49
 
1044
 50
 
1045
 51
 
1046
 52
 
1047
 53
 
1048
 54
 
1049
 55
 
1050
 56
 
1051
 57
 
1052
 58
 
1053
 59
 
1054
 60
 
1055
 61
 
1056
 62
 
1057
 63
 
1058
 64
 
1059
 65
 
1060
 66
 
1061
 67
 
1062
 68
 
1063
 69
 
1064
 70
 
1065
 71
 
1066
 72
 
1067
 73
 
1068
 74
 
1069
 75
 
1070
 76
 
1071
 77
 
1072
 78
 
1073
 79
 
1074
 80
 
1075
 81
 
1076
 82
 
1077
 83
 
1078
 84
 
1079
 85
 
1080
 86
 
1081
 87
 
1082
 88
 
1083
 89
 
1084
 90
 
1085
 91
 
1086
 92
 
1087
 93
 
1088
 94
 
1089
 95
 
1090
 96
 
1091
 97
 
1092
 98
 
1093
 99
 
1094
100
 
1095
101
 
1096
102
 
1097
103
 
1098
104
 
1099
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
1100
 
 
1101
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
1102
<span class="py-src-comment"># See LICENSE for details.</span>
 
1103
 
508
1104
<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>
509
1105
<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">failure</span>, <span class="py-src-variable">util</span>
510
1106
 
511
1107
<span class="py-src-string">&quot;&quot;&quot;
512
 
now we'll see what happens when you use 'addBoth'
513
 
 
 
1108
Now we'll see what happens when you use 'addBoth'.
514
1109
&quot;&quot;&quot;</span>
515
1110
 
516
1111
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
541
1136
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;both %s&quot;</span> % (<span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span>,)
542
1137
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tgot argument %r&quot;</span> % (<span class="py-src-variable">arg</span>,)
543
1138
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\tdoing something very important&quot;</span>
544
 
    <span class="py-src-comment"># we pass the argument we received to the next phase here
545
 
</span>    <span class="py-src-keyword">return</span> <span class="py-src-variable">arg</span>
 
1139
    <span class="py-src-comment"># we pass the argument we received to the next phase here</span>
 
1140
    <span class="py-src-keyword">return</span> <span class="py-src-variable">arg</span>
546
1141
 
547
1142
 
548
1143
 
549
1144
<span class="py-src-keyword">def</span> <span class="py-src-identifier">behindTheScenes</span>(<span class="py-src-parameter">result</span>):
550
 
    <span class="py-src-comment"># equivalent to d.callback(result)
551
 
</span>
 
1145
    <span class="py-src-comment"># equivalent to d.callback(result)</span>
 
1146
 
552
1147
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
553
1148
        <span class="py-src-keyword">try</span>:
554
1149
            <span class="py-src-variable">result</span> = <span class="py-src-variable">handleResult</span>(<span class="py-src-variable">result</span>)
567
1162
        <span class="py-src-keyword">pass</span>
568
1163
 
569
1164
 
570
 
    <span class="py-src-comment"># ---- this is equivalent to addBoth(doThisNoMatterWhat)
571
 
</span>
 
1165
    <span class="py-src-comment"># ---- this is equivalent to addBoth(doThisNoMatterWhat)</span>
 
1166
 
572
1167
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>):
573
1168
        <span class="py-src-keyword">try</span>:
574
1169
            <span class="py-src-variable">result</span> = <span class="py-src-variable">doThisNoMatterWhat</span>(<span class="py-src-variable">result</span>)
605
1200
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
606
1201
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
607
1202
    <span class="py-src-variable">deferredExample</span>()
608
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex4.py"><span class="filename">listings/deferred/deferred_ex4.py</span></a></div></div><pre>
 
1203
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex4.py"><span class="filename">listings/deferred/deferred_ex4.py</span></a></div></div>
 
1204
 
 
1205
<pre xml:space="preserve">
609
1206
callback 1
610
1207
        got result: success
611
1208
callback 2
623
1220
  File &quot;./deferred_ex4.py&quot;, line 32, in failAtHandlingResult
624
1221
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
625
1222
exceptions.RuntimeError: whoops! we encountered an error
626
 
</pre><p>You can see that the errback is called, (and consequently, the failure is
 
1223
</pre>
 
1224
 
 
1225
<p>You can see that the errback is called, (and consequently, the failure is
627
1226
trapped).  This is because doThisNoMatterWhat method returned the value it
628
 
received, a failure.</p><h2>addCallbacks: decision making based on previous success or failure<a name="auto8"></a></h2><p>As we've been seeing in the examples, the callback is a pair of
 
1227
received, a failure.</p>
 
1228
 
 
1229
<h2>addCallbacks: decision making based on previous success or failure<a name="auto8"/></h2>
 
1230
 
 
1231
<p>As we've been seeing in the examples, the callback is a pair of
629
1232
callback/errback.  Using addCallback or addErrback is actually a special case
630
1233
where one of the pair is a pass statement. If you want to make a decision
631
1234
based on whether or not the previous result in the chain was a failure or not
632
1235
(which is very rare, but included here for completeness), you use
633
1236
addCallbacks. Note that this is <strong>not</strong> the same thing as an
634
 
addCallback followed by an addErrback.</p><div class="py-listing"><pre>
635
 
<span class="py-src-comment">#!/usr/bin/python
636
 
</span>
 
1237
addCallback followed by an addErrback.</p>
 
1238
 
 
1239
 
 
1240
<div class="py-listing"><pre><p class="py-linenumber">  1
 
1241
  2
 
1242
  3
 
1243
  4
 
1244
  5
 
1245
  6
 
1246
  7
 
1247
  8
 
1248
  9
 
1249
 10
 
1250
 11
 
1251
 12
 
1252
 13
 
1253
 14
 
1254
 15
 
1255
 16
 
1256
 17
 
1257
 18
 
1258
 19
 
1259
 20
 
1260
 21
 
1261
 22
 
1262
 23
 
1263
 24
 
1264
 25
 
1265
 26
 
1266
 27
 
1267
 28
 
1268
 29
 
1269
 30
 
1270
 31
 
1271
 32
 
1272
 33
 
1273
 34
 
1274
 35
 
1275
 36
 
1276
 37
 
1277
 38
 
1278
 39
 
1279
 40
 
1280
 41
 
1281
 42
 
1282
 43
 
1283
 44
 
1284
 45
 
1285
 46
 
1286
 47
 
1287
 48
 
1288
 49
 
1289
 50
 
1290
 51
 
1291
 52
 
1292
 53
 
1293
 54
 
1294
 55
 
1295
 56
 
1296
 57
 
1297
 58
 
1298
 59
 
1299
 60
 
1300
 61
 
1301
 62
 
1302
 63
 
1303
 64
 
1304
 65
 
1305
 66
 
1306
 67
 
1307
 68
 
1308
 69
 
1309
 70
 
1310
 71
 
1311
 72
 
1312
 73
 
1313
 74
 
1314
 75
 
1315
 76
 
1316
 77
 
1317
 78
 
1318
 79
 
1319
 80
 
1320
 81
 
1321
 82
 
1322
 83
 
1323
 84
 
1324
 85
 
1325
 86
 
1326
 87
 
1327
 88
 
1328
 89
 
1329
 90
 
1330
 91
 
1331
 92
 
1332
 93
 
1333
 94
 
1334
 95
 
1335
 96
 
1336
 97
 
1337
 98
 
1338
 99
 
1339
100
 
1340
101
 
1341
102
 
1342
103
 
1343
104
 
1344
105
 
1345
106
 
1346
107
 
1347
108
 
1348
109
 
1349
110
 
1350
111
 
1351
112
 
1352
113
 
1353
114
 
1354
115
 
1355
116
 
1356
117
 
1357
118
 
1358
119
 
1359
120
 
1360
121
 
1361
122
 
1362
123
 
1363
124
 
1364
125
 
1365
126
 
1366
127
 
1367
128
 
1368
129
 
1369
130
 
1370
131
 
1371
132
 
1372
133
 
1373
134
 
1374
135
 
1375
136
 
1376
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
1377
 
 
1378
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
1379
<span class="py-src-comment"># See LICENSE for details.</span>
 
1380
 
637
1381
<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>
638
1382
<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">failure</span>, <span class="py-src-variable">util</span>
639
1383
 
640
1384
<span class="py-src-string">&quot;&quot;&quot;
641
 
now comes the more nuanced addCallbacks, which allows us to make a
 
1385
Now comes the more nuanced addCallbacks, which allows us to make a
642
1386
yes/no (branching) decision based on whether the result at a given point is
643
1387
a failure or not.
644
 
 
645
1388
&quot;&quot;&quot;</span>
646
1389
 
647
1390
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
693
1436
        <span class="py-src-keyword">pass</span>
694
1437
 
695
1438
 
696
 
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)
697
 
</span>
 
1439
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)</span>
 
1440
 
698
1441
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
699
1442
        <span class="py-src-keyword">try</span>:
700
1443
            <span class="py-src-variable">result</span> = <span class="py-src-variable">yesDecision</span>(<span class="py-src-variable">result</span>)
716
1459
        <span class="py-src-keyword">pass</span>
717
1460
 
718
1461
 
719
 
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)
720
 
</span>
 
1462
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)</span>
 
1463
 
721
1464
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
722
1465
        <span class="py-src-keyword">try</span>:
723
1466
            <span class="py-src-variable">result</span> = <span class="py-src-variable">yesDecision</span>(<span class="py-src-variable">result</span>)
765
1508
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
766
1509
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
767
1510
    <span class="py-src-variable">deferredExample</span>()
768
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex5.py"><span class="filename">listings/deferred/deferred_ex5.py</span></a></div></div><pre>
 
1511
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex5.py"><span class="filename">listings/deferred/deferred_ex5.py</span></a></div></div>
 
1512
 
 
1513
<pre xml:space="preserve">
769
1514
callback 1
770
1515
        got result: success
771
1516
        about to raise exception
777
1522
        wasn't a failure, so we can plow ahead
778
1523
callback 5
779
1524
        got result: go ahead!
780
 
</pre><p>Notice that our errback is never called. The noDecision method returns a
 
1525
</pre>
 
1526
 
 
1527
<p>Notice that our errback is never called. The noDecision method returns a
781
1528
non-failure so processing continues with the next callback. If we wanted to
782
1529
skip the callback at &quot;- A -&quot; because of the error, but do some kind of
783
1530
processing in response to the error, we would have used a passthru, and
784
 
returned the failure we received, as we see in this next example: </p><div class="py-listing"><pre>
785
 
<span class="py-src-comment">#!/usr/bin/python
786
 
</span>
 
1531
returned the failure we received, as we see in this next example: </p>
 
1532
 
 
1533
<div class="py-listing"><pre><p class="py-linenumber">  1
 
1534
  2
 
1535
  3
 
1536
  4
 
1537
  5
 
1538
  6
 
1539
  7
 
1540
  8
 
1541
  9
 
1542
 10
 
1543
 11
 
1544
 12
 
1545
 13
 
1546
 14
 
1547
 15
 
1548
 16
 
1549
 17
 
1550
 18
 
1551
 19
 
1552
 20
 
1553
 21
 
1554
 22
 
1555
 23
 
1556
 24
 
1557
 25
 
1558
 26
 
1559
 27
 
1560
 28
 
1561
 29
 
1562
 30
 
1563
 31
 
1564
 32
 
1565
 33
 
1566
 34
 
1567
 35
 
1568
 36
 
1569
 37
 
1570
 38
 
1571
 39
 
1572
 40
 
1573
 41
 
1574
 42
 
1575
 43
 
1576
 44
 
1577
 45
 
1578
 46
 
1579
 47
 
1580
 48
 
1581
 49
 
1582
 50
 
1583
 51
 
1584
 52
 
1585
 53
 
1586
 54
 
1587
 55
 
1588
 56
 
1589
 57
 
1590
 58
 
1591
 59
 
1592
 60
 
1593
 61
 
1594
 62
 
1595
 63
 
1596
 64
 
1597
 65
 
1598
 66
 
1599
 67
 
1600
 68
 
1601
 69
 
1602
 70
 
1603
 71
 
1604
 72
 
1605
 73
 
1606
 74
 
1607
 75
 
1608
 76
 
1609
 77
 
1610
 78
 
1611
 79
 
1612
 80
 
1613
 81
 
1614
 82
 
1615
 83
 
1616
 84
 
1617
 85
 
1618
 86
 
1619
 87
 
1620
 88
 
1621
 89
 
1622
 90
 
1623
 91
 
1624
 92
 
1625
 93
 
1626
 94
 
1627
 95
 
1628
 96
 
1629
 97
 
1630
 98
 
1631
 99
 
1632
100
 
1633
101
 
1634
102
 
1635
103
 
1636
104
 
1637
105
 
1638
106
 
1639
107
 
1640
108
 
1641
109
 
1642
110
 
1643
111
 
1644
112
 
1645
113
 
1646
114
 
1647
115
 
1648
116
 
1649
117
 
1650
118
 
1651
119
 
1652
120
 
1653
121
 
1654
122
 
1655
123
 
1656
124
 
1657
125
 
1658
126
 
1659
127
 
1660
128
 
1661
129
 
1662
130
 
1663
131
 
1664
132
 
1665
133
 
1666
134
 
1667
135
 
1668
136
 
1669
137
 
1670
138
 
1671
139
 
1672
140
 
1673
141
 
1674
142
 
1675
143
 
1676
144
 
1677
145
 
1678
146
 
1679
147
 
1680
148
 
1681
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
1682
 
 
1683
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
1684
<span class="py-src-comment"># See LICENSE for details.</span>
 
1685
 
787
1686
<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>
788
1687
<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">failure</span>, <span class="py-src-variable">util</span>
789
1688
 
790
1689
<span class="py-src-string">&quot;&quot;&quot;
791
 
now comes the more nuanced addCallbacks, which allows us to make a
 
1690
Now comes the more nuanced addCallbacks, which allows us to make a
792
1691
yes/no (branching) decision based on whether the result at a given point is
793
1692
a failure or not.
794
1693
 
795
1694
here, we return the failure from noDecisionPassthru, the errback argument to
796
 
the first addCallbacks method invocation, and see what happens
797
 
 
 
1695
the first addCallbacks method invocation, and see what happens.
798
1696
&quot;&quot;&quot;</span>
799
1697
 
800
1698
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
851
1749
        <span class="py-src-keyword">pass</span>
852
1750
 
853
1751
 
854
 
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)
855
 
</span>
 
1752
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)</span>
 
1753
 
856
1754
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
857
1755
        <span class="py-src-keyword">try</span>:
858
1756
            <span class="py-src-variable">result</span> = <span class="py-src-variable">yesDecision</span>(<span class="py-src-variable">result</span>)
874
1772
        <span class="py-src-keyword">pass</span>
875
1773
 
876
1774
 
877
 
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)
878
 
</span>
 
1775
    <span class="py-src-comment"># this is equivalent to addCallbacks(yesDecision, noDecision)</span>
 
1776
 
879
1777
    <span class="py-src-keyword">if</span> <span class="py-src-keyword">not</span> <span class="py-src-variable">isinstance</span>(<span class="py-src-variable">result</span>, <span class="py-src-variable">failure</span>.<span class="py-src-variable">Failure</span>): <span class="py-src-comment"># ---- callback</span>
880
1778
        <span class="py-src-keyword">try</span>:
881
1779
            <span class="py-src-variable">result</span> = <span class="py-src-variable">yesDecision</span>(<span class="py-src-variable">result</span>)
910
1808
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
911
1809
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>)
912
1810
 
913
 
    <span class="py-src-comment"># noDecisionPassthru will be called
914
 
</span>    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">yesDecision</span>, <span class="py-src-variable">noDecisionPassthru</span>)
 
1811
    <span class="py-src-comment"># noDecisionPassthru will be called</span>
 
1812
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">yesDecision</span>, <span class="py-src-variable">noDecisionPassthru</span>)
915
1813
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>) <span class="py-src-comment"># - A -</span>
916
1814
 
917
 
    <span class="py-src-comment"># noDecision will be called
918
 
</span>    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">yesDecision</span>, <span class="py-src-variable">noDecision</span>)
 
1815
    <span class="py-src-comment"># noDecision will be called</span>
 
1816
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallbacks</span>(<span class="py-src-variable">yesDecision</span>, <span class="py-src-variable">noDecision</span>)
919
1817
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>) <span class="py-src-comment"># - B -</span>
920
1818
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
921
1819
 
927
1825
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
928
1826
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
929
1827
    <span class="py-src-variable">deferredExample</span>()
930
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex6.py"><span class="filename">listings/deferred/deferred_ex6.py</span></a></div></div><pre>
 
1828
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex6.py"><span class="filename">listings/deferred/deferred_ex6.py</span></a></div></div>
 
1829
 
 
1830
<pre xml:space="preserve">
931
1831
callback 1
932
1832
        got result: success
933
1833
        about to raise exception
937
1837
        *doh*! a failure! quick! damage control!
938
1838
callback 4
939
1839
        got result: damage control successful!
940
 
</pre><p>Two things to note here. First, &quot;- A -&quot; was skipped, like we wanted it to,
 
1840
</pre>
 
1841
 
 
1842
<p>Two things to note here. First, &quot;- A -&quot; was skipped, like we wanted it to,
941
1843
and the second thing is that after &quot;- A -&quot;, noDecision is called, because
942
1844
<strong>it is the next errback that exists in the chain</strong>. It returns a
943
1845
non-failure, so processing continues with the next callback at &quot;- B -&quot;, and
944
 
the errback at the end of the chain is never called </p><h2>Hints, tips, common mistakes, and miscellaney<a name="auto9"></a></h2><h3>The deferred callback chain is stateful<a name="auto10"></a></h3><p>A deferred that has been called back will call it's addCallback and
 
1846
the errback at the end of the chain is never called </p>
 
1847
 
 
1848
<h2>Hints, tips, common mistakes, and miscellaney<a name="auto9"/></h2>
 
1849
 
 
1850
<h3>The deferred callback chain is stateful<a name="auto10"/></h3>
 
1851
 
 
1852
<p>A deferred that has been called back will call its addCallback and
945
1853
addErrback methods as appropriate in the order they are added, when they are
946
1854
added. So we see in the following example, deferredExample1 and
947
1855
deferredExample2 are equivalent. The first sets up the processing chain
948
1856
beforehand and then executes it, the other executes the chain as it is being
949
 
constructed.  This is because deferreds are <em>stateful</em>.  </p><div class="py-listing"><pre>
950
 
<span class="py-src-comment">#!/usr/bin/python
951
 
</span>
 
1857
constructed.  This is because deferreds are <em>stateful</em>.  </p>
 
1858
 
 
1859
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
1860
 2
 
1861
 3
 
1862
 4
 
1863
 5
 
1864
 6
 
1865
 7
 
1866
 8
 
1867
 9
 
1868
10
 
1869
11
 
1870
12
 
1871
13
 
1872
14
 
1873
15
 
1874
16
 
1875
17
 
1876
18
 
1877
19
 
1878
20
 
1879
21
 
1880
22
 
1881
23
 
1882
24
 
1883
25
 
1884
26
 
1885
27
 
1886
28
 
1887
29
 
1888
30
 
1889
31
 
1890
32
 
1891
33
 
1892
34
 
1893
35
 
1894
36
 
1895
37
 
1896
38
 
1897
39
 
1898
40
 
1899
41
 
1900
42
 
1901
43
 
1902
44
 
1903
45
 
1904
46
 
1905
47
 
1906
48
 
1907
49
 
1908
50
 
1909
51
 
1910
52
 
1911
53
 
1912
54
 
1913
55
 
1914
56
 
1915
57
 
1916
58
 
1917
59
 
1918
60
 
1919
61
 
1920
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
1921
 
 
1922
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
1923
<span class="py-src-comment"># See LICENSE for details.</span>
 
1924
 
952
1925
<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>
953
1926
<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">failure</span>, <span class="py-src-variable">util</span>
954
1927
 
979
1952
    <span class="py-src-keyword">raise</span> <span class="py-src-variable">RuntimeError</span>, <span class="py-src-string">&quot;whoops! we encountered an error&quot;</span>
980
1953
 
981
1954
<span class="py-src-keyword">def</span> <span class="py-src-identifier">deferredExample1</span>():
982
 
    <span class="py-src-comment"># this is another common idiom, since all add* methods
983
 
</span>    <span class="py-src-comment"># return the deferred instance, you can just chain your
984
 
</span>    <span class="py-src-comment"># calls to addCallback and addErrback
985
 
</span>
 
1955
    <span class="py-src-comment"># this is another common idiom, since all add* methods</span>
 
1956
    <span class="py-src-comment"># return the deferred instance, you can just chain your</span>
 
1957
    <span class="py-src-comment"># calls to addCallback and addErrback</span>
 
1958
 
986
1959
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>().<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">failAtHandlingResult</span>
987
1960
                       ).<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">handleResult</span>
988
1961
                       ).<span class="py-src-variable">addErrback</span>(<span class="py-src-variable">handleFailure</span>)
1004
1977
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;\n-------------------------------------------------\n&quot;</span>
1005
1978
    <span class="py-src-variable">Counter</span>.<span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
1006
1979
    <span class="py-src-variable">deferredExample2</span>()
1007
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex7.py"><span class="filename">listings/deferred/deferred_ex7.py</span></a></div></div><pre>
 
1980
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex7.py"><span class="filename">listings/deferred/deferred_ex7.py</span></a></div></div>
 
1981
 
 
1982
<pre xml:space="preserve">
1008
1983
callback 1
1009
1984
        got result: success
1010
1985
        about to raise exception
1033
2008
  File &quot;./deferred_ex7.py&quot;, line 35, in failAtHandlingResult
1034
2009
    raise RuntimeError, &quot;whoops! we encountered an error&quot;
1035
2010
exceptions.RuntimeError: whoops! we encountered an error
1036
 
</pre><p>This example also shows you the common idiom of chaining calls to
 
2011
</pre>
 
2012
 
 
2013
<p>This example also shows you the common idiom of chaining calls to
1037
2014
addCallback and addErrback.
1038
 
</p><h3>Don't call .callback() on deferreds you didn't create!<a name="auto11"></a></h3><p>It is an error to reinvoke deferreds callback or errback method, therefore
 
2015
</p>
 
2016
 
 
2017
<h3>Don't call .callback() on deferreds you didn't create!<a name="auto11"/></h3>
 
2018
 
 
2019
<p>It is an error to reinvoke deferreds callback or errback method, therefore
1039
2020
if you didn't create a deferred, <strong>do not under any
1040
2021
circumstances</strong> call its callback or errback.  doing so will raise
1041
 
an exception </p><h3>Callbacks can return deferreds<a name="auto12"></a></h3><p>If you need to call a method that returns a deferred within your callback
 
2022
an exception </p>
 
2023
 
 
2024
<h3>Callbacks can return deferreds<a name="auto12"/></h3>
 
2025
 
 
2026
<p>If you need to call a method that returns a deferred within your callback
1042
2027
chain, just return that deferred, and the result of the secondary deferred's
1043
2028
processing chain will become the result that gets passed to the next callback
1044
 
of the primary deferreds processing chain </p><div class="py-listing"><pre>
1045
 
<span class="py-src-comment">#!/usr/bin/python
1046
 
</span>
 
2029
of the primary deferreds processing chain </p>
 
2030
 
 
2031
<div class="py-listing"><pre><p class="py-linenumber"> 1
 
2032
 2
 
2033
 3
 
2034
 4
 
2035
 5
 
2036
 6
 
2037
 7
 
2038
 8
 
2039
 9
 
2040
10
 
2041
11
 
2042
12
 
2043
13
 
2044
14
 
2045
15
 
2046
16
 
2047
17
 
2048
18
 
2049
19
 
2050
20
 
2051
21
 
2052
22
 
2053
23
 
2054
24
 
2055
25
 
2056
26
 
2057
27
 
2058
28
 
2059
29
 
2060
30
 
2061
31
 
2062
32
 
2063
33
 
2064
34
 
2065
35
 
2066
36
 
2067
37
 
2068
38
 
2069
39
 
2070
40
 
2071
41
 
2072
42
 
2073
43
 
2074
44
 
2075
45
 
2076
46
 
2077
47
 
2078
48
 
2079
49
 
2080
50
 
2081
51
 
2082
52
 
2083
53
 
2084
54
 
2085
55
 
2086
56
 
2087
57
 
2088
58
 
2089
59
 
2090
60
 
2091
61
 
2092
62
 
2093
63
 
2094
64
 
2095
65
 
2096
66
 
2097
</p><span class="py-src-comment">#!/usr/bin/env python</span>
 
2098
 
 
2099
<span class="py-src-comment"># Copyright (c) 2009 Twisted Matrix Laboratories.</span>
 
2100
<span class="py-src-comment"># See LICENSE for details.</span>
 
2101
 
1047
2102
<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>
1048
2103
<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">failure</span>, <span class="py-src-variable">util</span>
1049
2104
 
1050
 
<span class="py-src-string">&quot;&quot;&quot;
1051
 
&quot;&quot;&quot;</span>
1052
2105
 
1053
2106
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
1054
2107
    <span class="py-src-variable">num</span> = <span class="py-src-number">0</span>
1106
2159
 
1107
2160
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
1108
2161
    <span class="py-src-variable">deferredExample</span>()
1109
 
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex8.py"><span class="filename">listings/deferred/deferred_ex8.py</span></a></div></div><pre>
 
2162
</pre><div class="caption">Source listing - <a href="listings/deferred/deferred_ex8.py"><span class="filename">listings/deferred/deferred_ex8.py</span></a></div></div>
 
2163
 
 
2164
<pre xml:space="preserve">
1110
2165
callback 1
1111
2166
        got result: I hope you'll agree: 
1112
2167
sub-callback a
1115
2170
        adding ' beautiful!' to result
1116
2171
callback 2
1117
2172
        got result: I hope you'll agree:  Deferreds  are  beautiful!
1118
 
</pre><h2>Conclusion<a name="auto13"></a></h2><p>Deferreds can be confusing, but only because they're so elegant and simple.
 
2173
</pre>
 
2174
 
 
2175
<h2>Conclusion<a name="auto13"/></h2>
 
2176
 
 
2177
<p>Deferreds can be confusing, but only because they're so elegant and simple.
1119
2178
There is a lot of logical power that can expressed with a deferred's
1120
2179
processing chain, and once you see what's going on behind the curtain, it's a
1121
 
lot easier to understand how to make use of what deferreds have to offer.</p></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'
 
2180
lot easier to understand how to make use of what deferreds have to offer.</p>
 
2181
 
 
2182
</div>
 
2183
 
 
2184
    <p><a href="index.html">Index</a></p>
 
2185
    <span class="version">Version: 9.0.0</span>
 
2186
  </body>
 
2187
</html>
 
 
b'\\ No newline at end of file'