~soren/nova/iptables-security-groups

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/doc/core/howto/gendefer.html

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html  PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
 
2
  <head>
 
3
<title>Twisted Documentation: Generating Deferreds</title>
 
4
<link href="stylesheet.css" rel="stylesheet" type="text/css"/>
 
5
  </head>
 
6
 
 
7
  <body bgcolor="white">
 
8
    <h1 class="title">Generating Deferreds</h1>
 
9
    <div class="toc"><ol><li><a href="#auto0">Class overview</a></li><ul><li><a href="#auto1">Basic Callback Functions</a></li></ul><li><a href="#auto2">What Deferreds don't do: make your code asynchronous</a></li><li><a href="#auto3">Advanced Processing Chain Control</a></li><li><a href="#auto4">Returning Deferreds from synchronous functions</a></li><li><a href="#auto5">Integrating blocking code with Twisted</a></li><li><a href="#auto6">Possible sources of error</a></li><ul><li><a href="#auto7">Firing Deferreds more than once is impossible</a></li><li><a href="#auto8">Synchronous callback execution</a></li></ul></ol></div>
 
10
    <div class="content">
 
11
 
 
12
<span/>
 
13
 
 
14
<p><code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.Deferred.html" title="twisted.internet.defer.Deferred">Deferred</a></code> objects are
 
15
signals that a function you have called does not yet have the data you want
 
16
available. When a function returns a Deferred object, your calling function
 
17
attaches callbacks to it to handle the data when available.</p>
 
18
 
 
19
<p>This document addresses the other half of the question: writing functions
 
20
that return Deferreds, that is, constructing Deferred objects, arranging for
 
21
them to be returned immediately without blocking until data is available, and
 
22
firing their callbacks when the data is available.</p>
 
23
 
 
24
<p>This document assumes that you are familiar with the asynchronous model used
 
25
by Twisted, and with <a href="defer.html" shape="rect">using deferreds returned by functions</a>
 
26
.</p>
 
27
 
 
28
<a name="class" shape="rect"/>
 
29
 
 
30
<h2>Class overview<a name="auto0"/></h2>
 
31
 
 
32
<p>This is an overview API reference for Deferred from the point of creating a
 
33
Deferred and firing its callbacks and errbacks.  It is not meant to be a
 
34
substitute for the docstrings in the Deferred class, but can provide
 
35
guidelines for its use.</p>
 
36
 
 
37
<p>There is a parallel overview of functions used by calling function which
 
38
the Deferred is returned to at <a href="defer.html#class" shape="rect">Using Deferreds</a>.</p>
 
39
 
 
40
<h3>Basic Callback Functions<a name="auto1"/></h3>
 
41
 
 
42
<ul>
 
43
  <li>
 
44
  <code class="py-prototype">callback(result)</code> 
 
45
  
 
46
  <p>Run success callbacks with the given result. <em>This
 
47
  can only be run once.</em> Later calls to this or
 
48
  <code>errback</code> will raise <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.AlreadyCalledError.html" title="twisted.internet.defer.AlreadyCalledError">twisted.internet.defer.AlreadyCalledError</a></code>.
 
49
  If further callbacks or errbacks are added after this
 
50
  point, addCallbacks will run the callbacks immediately.</p>
 
51
  </li>
 
52
  
 
53
  <li>
 
54
  <code class="py-prototype">errback(failure)</code> 
 
55
  
 
56
  <p>Run error callbacks with the given failure. <em>This can
 
57
  only be run once.</em> Later calls to this or
 
58
  <code>callback</code> will raise <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.AlreadyCalledError.html" title="twisted.internet.defer.AlreadyCalledError">twisted.internet.defer.AlreadyCalledError</a></code>.
 
59
  If further callbacks or errbacks are added after this
 
60
  point, addCallbacks will run the callbacks immediately.</p>
 
61
  </li>
 
62
</ul>
 
63
 
 
64
<h2>What Deferreds don't do: make your code asynchronous<a name="auto2"/></h2>
 
65
 
 
66
<p><em>Deferreds do not make the code magically not block.</em></p>
 
67
 
 
68
<p>Let's take this function as an example:</p>
 
69
 
 
70
<pre class="python"><p class="py-linenumber"> 1
 
71
 2
 
72
 3
 
73
 4
 
74
 5
 
75
 6
 
76
 7
 
77
 8
 
78
 9
 
79
10
 
80
11
 
81
12
 
82
13
 
83
14
 
84
15
 
85
16
 
86
17
 
87
18
 
88
19
 
89
20
 
90
21
 
91
22
 
92
23
 
93
24
 
94
25
 
95
26
 
96
27
 
97
28
 
98
29
 
99
30
 
100
31
 
101
32
 
102
33
 
103
34
 
104
35
 
105
36
 
106
37
 
107
38
 
108
39
 
109
40
 
110
41
 
111
42
 
112
43
 
113
44
 
114
45
 
115
46
 
116
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
117
    
 
118
<span class="py-src-variable">TARGET</span> = <span class="py-src-number">10000</span>
 
119
 
 
120
<span class="py-src-keyword">def</span> <span class="py-src-identifier">largeFibonnaciNumber</span>():
 
121
    <span class="py-src-comment"># create a Deferred object to return:</span>
 
122
    <span class="py-src-variable">d</span> = <span class="py-src-variable">defer</span>.<span class="py-src-variable">Deferred</span>()
 
123
 
 
124
    <span class="py-src-comment"># calculate the ten thousandth Fibonnaci number</span>
 
125
 
 
126
    <span class="py-src-variable">first</span> = <span class="py-src-number">0</span>
 
127
    <span class="py-src-variable">second</span> = <span class="py-src-number">1</span>
 
128
 
 
129
    <span class="py-src-keyword">for</span> <span class="py-src-variable">i</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">xrange</span>(<span class="py-src-variable">TARGET</span> - <span class="py-src-number">1</span>):
 
130
        <span class="py-src-variable">new</span> = <span class="py-src-variable">first</span> + <span class="py-src-variable">second</span>
 
131
        <span class="py-src-variable">first</span> = <span class="py-src-variable">second</span>
 
132
        <span class="py-src-variable">second</span> = <span class="py-src-variable">new</span>
 
133
        <span class="py-src-keyword">if</span> <span class="py-src-variable">i</span> % <span class="py-src-number">100</span> == <span class="py-src-number">0</span>:
 
134
            <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;Progress: calculating the %dth Fibonnaci number&quot;</span> % <span class="py-src-variable">i</span>
 
135
 
 
136
    <span class="py-src-comment"># give the Deferred the answer to pass to the callbacks:</span>
 
137
    <span class="py-src-variable">d</span>.<span class="py-src-variable">callback</span>(<span class="py-src-variable">second</span>)
 
138
 
 
139
    <span class="py-src-comment"># return the Deferred with the answer:</span>
 
140
    <span class="py-src-keyword">return</span> <span class="py-src-variable">d</span>
 
141
 
 
142
<span class="py-src-keyword">import</span> <span class="py-src-variable">time</span>
 
143
 
 
144
<span class="py-src-variable">timeBefore</span> = <span class="py-src-variable">time</span>.<span class="py-src-variable">time</span>()
 
145
 
 
146
<span class="py-src-comment"># call the function and get our Deferred</span>
 
147
<span class="py-src-variable">d</span> = <span class="py-src-variable">largeFibonnaciNumber</span>()
 
148
 
 
149
<span class="py-src-variable">timeAfter</span> = <span class="py-src-variable">time</span>.<span class="py-src-variable">time</span>()
 
150
 
 
151
<span class="py-src-keyword">print</span> <span class="py-src-string">&quot;Total time taken for largeFibonnaciNumber call: %0.3f seconds&quot;</span> %
 
152
      (<span class="py-src-variable">timeAfter</span> - <span class="py-src-variable">timeBefore</span>)
 
153
 
 
154
<span class="py-src-comment"># add a callback to it to print the number</span>
 
155
 
 
156
<span class="py-src-keyword">def</span> <span class="py-src-identifier">printNumber</span>(<span class="py-src-parameter">number</span>):
 
157
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;The %dth Fibonacci number is %d&quot;</span> % (<span class="py-src-variable">TARGET</span>, <span class="py-src-variable">number</span>)
 
158
 
 
159
<span class="py-src-keyword">print</span> <span class="py-src-string">&quot;Adding the callback now.&quot;</span>
 
160
 
 
161
<span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">printNumber</span>)
 
162
</pre>
 
163
 
 
164
<p>You will notice that despite creating a Deferred in the
 
165
<code>largeFibonnaciNumber</code> function, these things happened:</p>
 
166
<ul>
 
167
<li>the &quot;Total time taken for largeFibonnaciNumber call&quot; output
 
168
shows that the function did not return immediately as asynchronous functions
 
169
are expected to do; and</li>
 
170
<li>rather than the callback being added before the result was available and
 
171
called after the result is available, it isn't even added until after the
 
172
calculation has been completed.</li>
 
173
</ul>
 
174
 
 
175
<p> The function completed its calculation before returning, blocking the
 
176
process until it had finished, which is exactly what asynchronous functions
 
177
are not meant to do.  Deferreds are not a non-blocking talisman: they are a
 
178
signal for asynchronous functions to <em>use</em> to pass results onto
 
179
callbacks, but using them does not guarantee that you have an asynchronous
 
180
function.</p>
 
181
 
 
182
 
 
183
<h2>Advanced Processing Chain Control<a name="auto3"/></h2>
 
184
 
 
185
<ul>
 
186
  <li>
 
187
  <code class="py-prototype">pause()</code> 
 
188
  
 
189
  <p>Cease calling any methods as they are added, and do not
 
190
  respond to <code>callback</code>, until
 
191
  <code>self.unpause()</code> is called.</p>
 
192
  </li>
 
193
  
 
194
  <li>
 
195
  <code class="py-prototype">unpause()</code> 
 
196
  
 
197
  <p>If <code>callback</code> has been called on this
 
198
  Deferred already, call all the callbacks that have been
 
199
  added to this Deferred since <code>pause</code> was
 
200
  called.</p>
 
201
  
 
202
  <p>Whether it was called or not, this will put this
 
203
  Deferred in a state where further calls to
 
204
  <code>addCallbacks</code> or <code>callback</code> will
 
205
  work as normal.</p>
 
206
  </li>
 
207
</ul>
 
208
 
 
209
<h2>Returning Deferreds from synchronous functions<a name="auto4"/></h2>
 
210
 
 
211
<p>Sometimes you might wish to return a Deferred from a synchronous function.
 
212
There are several reasons why, the major two are maintaining API compatibility
 
213
with another version of your function which returns a Deferred, or allowing
 
214
for the possiblity that in the future your function might need to be
 
215
asynchronous.</p>
 
216
 
 
217
<p>In the <a href="defer.html" shape="rect">Using Deferreds</a> reference, we gave the
 
218
following example of a synchronous function:</p>
 
219
 
 
220
<div class="py-listing"><pre><p class="py-linenumber">1
 
221
2
 
222
3
 
223
4
 
224
5
 
225
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">synchronousIsValidUser</span>(<span class="py-src-parameter">user</span>):
 
226
    <span class="py-src-string">'''
 
227
    Return true if user is a valid user, false otherwise
 
228
    '''</span>
 
229
    <span class="py-src-keyword">return</span> <span class="py-src-variable">user</span> <span class="py-src-keyword">in</span> [<span class="py-src-string">&quot;Alice&quot;</span>, <span class="py-src-string">&quot;Angus&quot;</span>, <span class="py-src-string">&quot;Agnes&quot;</span>]
 
230
</pre><div class="caption">Source listing - <a href="listings/deferred/synch-validation.py"><span class="filename">listings/deferred/synch-validation.py</span></a></div></div>
 
231
 
 
232
<p>While we can require that callers of our function wrap our synchronous
 
233
result in a Deferred using <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.maybeDeferred.html" title="twisted.internet.defer.maybeDeferred">maybeDeferred</a></code>, for the sake of API
 
234
compatibility it is better to return a Deferred ourself using  <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.succeed.html" title="twisted.internet.defer.succeed">defer.succeed</a></code>:</p>
 
235
 
 
236
<pre class="python"><p class="py-linenumber"> 1
 
237
 2
 
238
 3
 
239
 4
 
240
 5
 
241
 6
 
242
 7
 
243
 8
 
244
 9
 
245
10
 
246
11
 
247
12
 
248
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">defer</span>
 
249
 
 
250
<span class="py-src-keyword">def</span> <span class="py-src-identifier">immediateIsValidUser</span>(<span class="py-src-parameter">user</span>):
 
251
    <span class="py-src-string">'''
 
252
    Returns a Deferred resulting in true if user is a valid user, false
 
253
    otherwise
 
254
    '''</span>
 
255
    
 
256
    <span class="py-src-variable">result</span> = <span class="py-src-variable">user</span> <span class="py-src-keyword">in</span> [<span class="py-src-string">&quot;Alice&quot;</span>, <span class="py-src-string">&quot;Angus&quot;</span>, <span class="py-src-string">&quot;Agnes&quot;</span>]
 
257
    
 
258
    <span class="py-src-comment"># return a Deferred object already called back with the value of result</span>
 
259
    <span class="py-src-keyword">return</span> <span class="py-src-variable">defer</span>.<span class="py-src-variable">succeed</span>(<span class="py-src-variable">result</span>)
 
260
</pre>
 
261
 
 
262
<p>There is an equivalent <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.defer.fail.html" title="twisted.internet.defer.fail">defer.fail</a></code> method to return a Deferred with the
 
263
errback chain already fired.</p>
 
264
 
 
265
<h2>Integrating blocking code with Twisted<a name="auto5"/></h2>
 
266
 
 
267
<p>At some point, you are likely to need to call a blocking function: many
 
268
functions in third party libraries will have long running blocking functions.
 
269
There is no way to 'force' a function to be asynchronous: it must be written
 
270
that way specifically. When using Twisted, your own code should be
 
271
asynchronous, but there is no way to make third party functions asynchronous
 
272
other than rewriting them.</p>
 
273
 
 
274
<p>In this case, Twisted provides the ability to run the blocking code in a
 
275
separate thread rather than letting it block your application. The <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.internet.threads.deferToThread.html" title="twisted.internet.threads.deferToThread">twisted.internet.threads.deferToThread</a></code> function will set up
 
276
a thread to run your blocking function, return a Deferred and later fire that
 
277
Deferred when the thread completes.</p>
 
278
 
 
279
<p>Let's assume our <code class="python">largeFibonnaciNumber</code> function
 
280
from above is in a third party library (returning the result of the
 
281
calculation, not a Deferred) and is not easily modifiable to be finished in
 
282
discrete blocks. This example shows it being called in a thread, unlike in the
 
283
earlier section we'll see that the operation does not block our entire
 
284
program:</p>
 
285
 
 
286
<pre class="python"><p class="py-linenumber"> 1
 
287
 2
 
288
 3
 
289
 4
 
290
 5
 
291
 6
 
292
 7
 
293
 8
 
294
 9
 
295
10
 
296
11
 
297
12
 
298
13
 
299
14
 
300
15
 
301
16
 
302
17
 
303
18
 
304
19
 
305
20
 
306
21
 
307
22
 
308
23
 
309
24
 
310
25
 
311
26
 
312
27
 
313
28
 
314
29
 
315
30
 
316
31
 
317
32
 
318
33
 
319
34
 
320
35
 
321
36
 
322
37
 
323
38
 
324
39
 
325
40
 
326
41
 
327
42
 
328
43
 
329
44
 
330
45
 
331
</p><span class="py-src-keyword">def</span> <span class="py-src-identifier">largeFibonnaciNumber</span>():
 
332
    <span class="py-src-string">&quot;&quot;&quot;
 
333
    Represent a long running blocking function by calculating
 
334
    the TARGETth Fibonnaci number
 
335
    &quot;&quot;&quot;</span>
 
336
    <span class="py-src-variable">TARGET</span> = <span class="py-src-number">10000</span>
 
337
 
 
338
    <span class="py-src-variable">first</span> = <span class="py-src-number">0</span>
 
339
    <span class="py-src-variable">second</span> = <span class="py-src-number">1</span>
 
340
 
 
341
    <span class="py-src-keyword">for</span> <span class="py-src-variable">i</span> <span class="py-src-keyword">in</span> <span class="py-src-variable">xrange</span>(<span class="py-src-variable">TARGET</span> - <span class="py-src-number">1</span>):
 
342
        <span class="py-src-variable">new</span> = <span class="py-src-variable">first</span> + <span class="py-src-variable">second</span>
 
343
        <span class="py-src-variable">first</span> = <span class="py-src-variable">second</span>
 
344
        <span class="py-src-variable">second</span> = <span class="py-src-variable">new</span>
 
345
 
 
346
    <span class="py-src-keyword">return</span> <span class="py-src-variable">second</span>
 
347
 
 
348
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">internet</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">threads</span>, <span class="py-src-variable">reactor</span>
 
349
 
 
350
<span class="py-src-keyword">def</span> <span class="py-src-identifier">fibonacciCallback</span>(<span class="py-src-parameter">result</span>):
 
351
    <span class="py-src-string">&quot;&quot;&quot;
 
352
    Callback which manages the largeFibonnaciNumber result by
 
353
    printing it out
 
354
    &quot;&quot;&quot;</span>
 
355
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;largeFibonnaciNumber result =&quot;</span>, <span class="py-src-variable">result</span>
 
356
    <span class="py-src-comment"># make sure the reactor stops after the callback chain finishes,</span>
 
357
    <span class="py-src-comment"># just so that this example terminates</span>
 
358
    <span class="py-src-variable">reactor</span>.<span class="py-src-variable">stop</span>()
 
359
 
 
360
<span class="py-src-keyword">def</span> <span class="py-src-identifier">run</span>():
 
361
    <span class="py-src-string">&quot;&quot;&quot;
 
362
    Run a series of operations, deferring the largeFibonnaciNumber
 
363
    operation to a thread and performing some other operations after
 
364
    adding the callback
 
365
    &quot;&quot;&quot;</span>
 
366
    <span class="py-src-comment"># get our Deferred which will be called with the largeFibonnaciNumber result</span>
 
367
    <span class="py-src-variable">d</span> = <span class="py-src-variable">threads</span>.<span class="py-src-variable">deferToThread</span>(<span class="py-src-variable">largeFibonnaciNumber</span>)
 
368
    <span class="py-src-comment"># add our callback to print it out</span>
 
369
    <span class="py-src-variable">d</span>.<span class="py-src-variable">addCallback</span>(<span class="py-src-variable">fibonacciCallback</span>)
 
370
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;1st line after the addition of the callback&quot;</span>
 
371
    <span class="py-src-keyword">print</span> <span class="py-src-string">&quot;2nd line after the addition of the callback&quot;</span>
 
372
 
 
373
<span class="py-src-keyword">if</span> <span class="py-src-variable">__name__</span> == <span class="py-src-string">'__main__'</span>:
 
374
    <span class="py-src-variable">run</span>()
 
375
    <span class="py-src-variable">reactor</span>.<span class="py-src-variable">run</span>()
 
376
</pre>
 
377
 
 
378
<h2>Possible sources of error<a name="auto6"/></h2>
 
379
 
 
380
<p>Deferreds greatly simplify the process of writing asynchronous code by
 
381
providing a standard for registering callbacks, but there are some subtle and
 
382
sometimes confusing rules that you need to follow if you are going to use
 
383
them. This mostly applies to people who are writing new systems that use
 
384
Deferreds internally, and not writers of applications that just add callbacks
 
385
to Deferreds produced and processed by other systems. Nevertheless, it is good
 
386
to know.</p>
 
387
 
 
388
<h3>Firing Deferreds more than once is impossible<a name="auto7"/></h3>
 
389
 
 
390
<p>Deferreds are one-shot. You can only call <code>Deferred.callback</code> or
 
391
<code>Deferred.errback</code> once. The processing chain continues each time
 
392
you add new callbacks to an already-called-back-to Deferred.</p>
 
393
 
 
394
<h3>Synchronous callback execution<a name="auto8"/></h3>
 
395
 
 
396
<p>If a Deferred already has a result available, addCallback
 
397
<strong>may</strong> call the callback synchronously: that is, immediately
 
398
after it's been added.  In situations where callbacks modify state, it is
 
399
might be desirable for the chain of processing to halt until all callbacks are
 
400
added. For this, it is possible to <code>pause</code> and <code>unpause</code>
 
401
a Deferred's processing chain while you are adding lots of callbacks.</p>
 
402
 
 
403
<p>Be careful when you use these methods! If you <code>pause</code> a
 
404
Deferred, it is <em>your</em> responsibility to make sure that you unpause it.
 
405
The function adding the callbacks must unpause a paused Deferred, it should
 
406
<em>never</em> be the responsibility of the code that actually fires the
 
407
callback chain by calling <code>callback</code> or <code>errback</code> as
 
408
this would negate its usefulness!</p>
 
409
 
 
410
</div>
 
411
 
 
412
    <p><a href="index.html">Index</a></p>
 
413
    <span class="version">Version: 10.0.0</span>
 
414
  </body>
 
415
</html>
 
 
b'\\ No newline at end of file'