Anda di halaman 1dari 192

Twisted

Dave Peticolas
Nina Evseenko

1.1

. . . . . . . . . . . . . . . . . . . . . . . . . . .

1.2

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

1.3

1.4

. . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . .

10
12
13

2.1

. . . . . . . . . . . . . . . . . . .

13

2.2

. . . . . . . . . . . . . . . . .

13

2.3

. . . . . . . . . . . . . . . . . . . . . . . .

13

2.4

. . . . . . . . . . . . . . . . . . . . . .

15

2.5

. . . . . . . . . . . . . . . . . . . . . .

16

2.6

. . . . . . . . . . . . . . . . . . . . . . .

17

2.7

20

. . . . . . . . . . . . . . . . . . . . . . . . . . .

Twisted

21

3.1

- Twisted . . . . . . . . . . . . . . . .

21

3.2

, Twisted

23

3.3

callback'?

3.4

, Twisted

3.5

, Twisted

3.6

, . . . . . . . . . . . . . . . . . . . . . . .

28

3.7

28

. . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . .

24

. . . . . . . . . . . . . . . . . . . . . .

26

. . . . . . . . . . . . . . . . . .

. . . . . . . . . . . . . . . . . . . . . . . . . . .

Twisted

27

29

4.1

Twisted

. . . . . . . . . . . . . . . . . .

29

4.2

Twisted . . . . . . . . . . . . . . . . . . . . . . .

30

4.3

callback' . . . . . . . . . . . . . . . . . . . . . . . .

32

4.4

34

4.5

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .

Twisted

35
36

5.1

. . . . . . . . . . . . . . . . .

5.2

. . . . . . . . . . . . . . . . . . . . . . . .

37

5.3

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

38

5.4

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

38

5.5

. . . . . . . . . . . . . . . . . . . . .

39

5.6

2.0: .0 . . . . . . . . . . . . .

40

5.7

45

. . . . . . . . . . . . . . . . . . . . . . .

36

5.8

5.9

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .

45
45

46

6.1

. . . . . . . . . . . . . . . . . . . . . . . . .

46

6.2

3.0

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

47

6.3

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

48

6.4

. . . . . . . . . . . . . . . . . . . . . . . .

50

6.5

3.1

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

53

6.6

6.7

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .

53
54
55

7.1

. . . . . . . . . . . .

7.2

Deferred . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

58

7.3

64

7.4

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .

55

64

65

8.1

4.0

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

65

8.2

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

66

8.3

deferred', callback', . . . . . .

68

8.4

70

8.5

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . .

Deferred',

71
72

9.1

callback'

. . . . . . . . . . . . . .

72

9.2

Deferred' . . . . . . . . . . . . . . .

77

9.3

Callback' Errback', . . . . . . . . . . . . . . . . .

81

9.4

Deferred

. . . . . . . . . . . . . . . . . . . . . . .

81

9.5

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

82

9.6

. . . . . . . . . . . . . . . . . . . . . . . . . . .

10

82
84

10.1 5.0

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

10.2 5.1

. . . . . . . . . . . . . . . . . . . . . . . . . . . .

89

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

91

10.3

10.4

. . . . . . . . . . . . . . . . . . . . . . . . . . .

84

92

11

93

11.1 Twisted . . . . . . . . . . . . . . . . . . .

93

11.2 . . . . . . . . . . . . . . . . . . . . . . . . . . . .

94

11.3

97

. . . . . . . . . . . . . . . . . . . . . . . . . . .

12 ,

98

12.1 . . . . . . . . . . . . . . . . . . . . . . . . .

98

12.2 . . . . . . . . . . . . . . . . . . .

98

12.3

99

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

12.4

. . . . . . . . . . . . . . . . . . . . . . . . . 101

12.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
12.6
12.7

. . . . . . . . . . . . . . . . . . . . . . . . 102

. . . . . . . . . . . . . . . . . . . . . . . . . . . 103

13 Deferred' Deferred'

13.1

104

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104

13.2 6.0

. . . . . . . . . . . . . . . . . . . . . . . . . . . . 106

13.3 . . . . . . . . . . . . . . . . . . . . . . 109
13.4

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109

13.5

. . . . . . . . . . . . . . . . . . . . . . . . . . . 109

14 , Deferred Deferred'

14.1

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111

14.2 1.0

. . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

14.3
14.4 2.0
14.5

. . . . . . . . . . . . . . . . . . . . . . . . . . 115

. . . . . . . . . . . . . . . . . . . . . . . . . . . . 116

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117

14.6

. . . . . . . . . . . . . . . . . . . . . . . . . . . 118

15

15.1
15.2

111

120

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120

15.3 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
15.4

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123

15.5

. . . . . . . . . . . . . . . . . . . . . . . . . . . 123

16 Twisted

16.1
16.2

124

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
. . . . . . . . . . . . . . . . . . . . . . . . . . . . 124

16.2.1 IService

. . . . . . . . . . . . . . . . . . . . . . . . . . 124

16.2.2 IServiceCollection . . . . . . . . . . . . . . . . . . . . . 126

16.2.3 Application

. . . . . . . . . . . . . . . . . . . . . . . . 126

16.2.4 Twisted . . . . . . . . . . . . . . . . . . . 127


16.3 FastPoetry 2.0 . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
16.3.1 Twisted tac . . . . . . . . . . . . . . . . . . . . 128
16.3.2 . . . . . . . . . . . . . . . . . . . . . . 130
16.3.3

. . . . . . . . . . . . . . . . . . . . . 132

16.4 Twisted . . . . . . . . . . . . . . . . . . 133


16.4.1 IPlugin . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
16.4.2 IServiceMaker . . . . . . . . . . . . . . . . . . . . . . . 135
16.5 Fast Poetry 3.0
16.6

. . . . . . . . . . . . . . . . . . . . . . . . . . 135

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138

16.7

. . . . . . . . . . . . . . . . . . . . . . . . . . . 138

17 callback'

17.1

139

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139

17.1.1 . . . . . . . . . . . . . . . 139
17.2 callback' . . . . . . . . . . . . . . . . . . . . . . 141
17.2.1 inlineCallbacks
17.3 7.0

. . . . . . . . . . . . . . . . . . . . . . 143

. . . . . . . . . . . . . . . . . . . . . . . . . . . . 144

17.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
17.5

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148

17.6

. . . . . . . . . . . . . . . . . . . . . . . . . . . 148

18 Deferred'

18.1

150

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150

18.2 DeferredList . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150


18.3 8.0

. . . . . . . . . . . . . . . . . . . . . . . . . . . . 155

18.4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
18.5

. . . . . . . . . . . . . . . . . . . . . . . . . . . 155

19 deferred'

19.1

157

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157

19.2 deferred'

. . . . . . . . . . . . . . . . . . 158

19.3 Deferred'

. . . . . . . . . . . . 161

19.4 3.0 . . . . . . . . . . . . . . . . . . . . . 165


19.5 . . . . . . . . . . . . . . . . . . . . 167
19.6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
19.7 . . . . . . . . . . . . . . . . . . . . . . 169
19.8

. . . . . . . . . . . . . . . . . . . . . . . . . . . 169

20 : Twisted Erlang

20.1

171

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171

20.2 . . . . . . . . . . . . . . 172
20.3 Erlang

. . . . . . . . . . . . . . . . . . . . . . . . 173

20.4 Erlang . . . . . . . . . . . . . . . . . . . 176


20.5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
20.6 . . . . . . . . . . . . . . . . 182
20.7

. . . . . . . . . . . 183

21 Twisted Haskell

21.1

184

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184

21.2
21.3 Haskell

. . . . . . . . . . . . . . . 184

. . . . . . . . . . . . . . . . . . . . . . . . . . 187

21.4 . . . . . . . . . . . . . . . 189
21.5
22

. . . . . . 190
191

22.1 . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
22.2
22.3

. . . . . . . . . . . . . . . . . . . . . . . 191

. . . . . . . . . . . . . . . . . . . . . . . . . . . 191

22.4

. . . . . . . . . . . . . . . . . . . . . . 191

. ,
Twisted Introduction, Dave Peticolas.

1.1

Twisted : -
, Twisted? ,
.
, . Twisted , . Twisted ,
, . , Twisted
, Twisted, , .
, , - Twisted.
Twisted. ,
Python'. Twisted,
,
. Twisted - ,
. , Twisted, , Twisted , .
.
, , Twisted. - .

1.2

, . , ,
, .

,
, , . ,  : ,
.
, , -
, 1 :

. 1:
. ,
, . , , , .
,
2:

. 2:
. ,

/ , , . ,
, ,
. ,
, . , .
, . , , ,
2.
3:

. 3: Ac
.
, , ,
, - .
, , ,
2, 3,
.
.
. -

. , ,
,
. , ,
. , .
, ,
. ,
, 
.

1.3

, , ,
, , .
, .

, .
, ,
,
, .
, ,
, ,
.
?
. -
, ,
,  .
, , . , ,
, , . , ,
4:
, () . ? -

10

. 4:

-,
.
,
. , , -,
. (blocking
program).
, 4 ,
3.
. - , , , , .  , ,
(non-blocking
program). , , ,
. ,
, .
, :
1. ,
, .

11

2. -, ,
, , .
3. .
(, web ) -. -
. . ,
Twisted - .

1.4

. , - , , ( Twisted),
, , Python'.

12

.
- .

2.1

, Python' Python'. ,
Python- socket, . Python,
, , .

2.2

Linux'. ,
Unix (Mac OSX FreeBSD).
, Python Twisted. Python
2.5 Twisted 8.2.0.
. .
zip tar , git . git
, git , , ,
.
SVG. :

git clone git://github.com/jdavisp3/twisted-intro.git


: , ( README).

2.3

, ,
, , ,

13

. , ,
, loopback
. - ,
, .
- , . poetry
John Donne, W.B. Yeats, Edgar Allen Poe. ,
.
blocking-server/slowpoetry.py.
:

python blocking-server/slowpoetry.py poetry/ecstasy.txt


Ecstasy John
Donne.
. , Twisted,
. , .
, 10 0.1 ,

--num-bytes

--delay.

, 50 5

, :

python blocking-server/slowpoetry.py --num-bytes 50 --delay 5 poetry/ecstasy.txt


, , . ,
. , , , , .
:

python blocking-server/slowpoetry.py --port 10000 poetry/ecstasy.txt


netcat ( nc),
:

netcat localhost 10000



. ! ,
. , , .

14

, "loopback".
,
iface.
, ,
,
, .
, .
,
Peak Oil , , , ,
, . , , ,
, , -
,
.
c .

2.4

,
.
,
1. ,
:

python blocking-server/slowpoetry.py --port 10000 poetry/ecstasy.txt --num-bytes 30


python blocking-server/slowpoetry.py --port 10001 poetry/fascination.txt
python blocking-server/slowpoetry.py --port 10002 poetry/science.txt
, , , . ,
chunk' 30 , 10, , ,
.
.
blocking-client/getpoetry.py, , .
:

python blocking-client/get-poetry.py 10000 10001 10002

15

,
. ,
,
,
. ,
:

Task 1: get
Task 1: got
Task 2: get
Task 2: got
Task 3: get
Task 3: got
Got 3 poems

poetry from: 127.0.0.1:10000


3003 bytes of poetry from 127.0.0.1:10000 in 0:00:10.126361
poetry from: 127.0.0.1:10001
623 bytes of poetry from 127.0.0.1:10001 in 0:00:06.321777
poetry from: 127.0.0.1:10002
653 bytes of poetry from 127.0.0.1:10002 in 0:00:06.617523
in 0:00:23.065661

1,
. .

--delay.

.

,
.

2.5

, Twisted. . , .
, . , async-client/get-poetry.py, :

python async-client/get-poetry.py 10000 10001 10002


:

Task 1: got 30 bytes of poetry


Task 2: got 10 bytes of poetry
Task 3: got 10 bytes of poetry
Task 1: got 30 bytes of poetry
Task 2: got 10 bytes of poetry
...
Task 1: 3003 bytes of poetry
Task 2: 623 bytes of poetry
Task 3: 653 bytes of poetry
Got 3 poems in 0:00:10.133169

from
from
from
from
from

127.0.0.1:10000
127.0.0.1:10001
127.0.0.1:10002
127.0.0.1:10000
127.0.0.1:10001

16

, . ,
, . , , 3.

--delay

(,

, ) ,
"" , . .
, , , 10 ,
23
. 3
4. ,
, .
, : , print!
. shell', , print

. , ,
pipeline ,
-
. Twisted , , , print, , Twisted.

2.6

. :
1.
.
2. , , setblocking(0).
3. select select () ,

17

.
4. ,
.
get_poetry.
:
1. () select',
.
2. , , , ,
.
3. .
( main),
. . , ,
.
. select' ,
, ,
, .
( ),
,
get_poetry. ,
, .
, , , reactor. 5:

18

. 5: reactor'

reactor', . ,
"event loop". , select ,
select -. select
, "" ,
. , select - -, (
) . API,
, ,
select, . , , :
( ) ,
-.
, select

- . (reactive system) -,
-, .
-,
.
,
reactor, ,
. .
reactor
, :

19

1.
-.
2. ,
.
reactor :
1. ,
.
2. ,
reactor .
3. ,
.
, Twisted - , -
reactor .
Twisted,
Twisted!

2.7

1. ,
.
2. get_poetry,
? ?
3. get_poetry ,
?
?

20

Twisted

3.1

- Twisted

, Twisted. C Twisted , c .
2, Twisted
8.2.0. API Twisted , API,
,
c . Twisted,
.
Twisted .
basic-twisted/simple.py.

from twisted.internet import reactor


reactor.run()
:

python basic-twisted/simple.py
, Twisted - Reactor, Twisted ,
reactor event loop,
Twisted . reactor, ,
.
. , CtrlC, .
- - (, ). , ,
. , busy loop,
. , . ,
. reactor
5, , ( , select ).
:
1. Twisted reactor.run().
2. , .
, main .

21

3. .
4. , .
5. reactor , .
. Twisted reactor - Singleton. reactor, .
reactor twisted.internet,
. :
(twisted.internet.selectreactor.py).
Twisted .
2, select' -
. , Twisted select, Twisted . , twisted.internet.pollreactor, poll select.
twisted.internet.reactor. pollreactor:

from twisted.internet import pollreactor


pollreactor.install()
twisted.internet.reactor , Twisted reactor
select. reactor , ,
, .
, , Twisted
,
. reactor , , .
Twisted , pollreactor, basic-twisted/simple-poll.py:

from twisted.internet import pollreactor


pollreactor.install()
from twisted.internet import reactor
reactor.run()
, poll , ,
select .
.
Twisted .

22

3.2

, Twisted

Twisted, - . , , ,
:

def hello():
print 'Hello from the reactor loop!'
print 'Lately I feel like I\'m stuck in a rut.'
from twisted.internet import reactor
reactor.callWhenRunning(hello)
print 'Starting the reactor.'
reactor.run()
basic-twisted/hello.py. :

Starting the reactor.


Hello from the reactor loop!
Lately I feel like I'm stuck in a rut.
,
, .
, hello , reactor . , ,
Twisted . callWhenRunning ,
Twisted. , ,
callWhenRunning , reactor.
callback (, hello), Twisted ( - ), Twisted , ""
.
, reactor . Twisted
,
callback',
Twisted, API.
, Twisted , :

import traceback
def stack():
print 'The python stack:'
traceback.print_stack()

23

from twisted.internet import reactor


reactor.callWhenRunning(stack)
reactor.run()
basic-twisted/stack.py, -
:

The python stack:


...
reactor.run() <-- This is where we called the reactor
...
... <-- A bunch of Twisted function calls
...
traceback.print_stack() <-- The second line in the stack function
,
reactor.run() callback'.

3.3

callback'?

Twisted , callback'.
Python Medusa asyncore . , GUI , GTK QT,
.
:
1. reactor .
2. , Twisted,
, .
3. .
4. ,
.
5. reactor
.
callback', .

24

6 , :

. 6: reactor,

6 callback':
1. callback' , Twisted
.
2. callback' , Twisted .
3. .
4. callback'.
callback-, Twisted . , callback'
. - callback'. , . Twisted
,
. , , Twisted .

25

( pipe)
. , , , Twisted API,
. , Python
. , os.system
, . Twisted, os.system Twisted API .

3.4

, Twisted

, y Twisted , stop. reactor


, , .
Twisted , reactor
"". 8.2.0, reactor
.
basic-twisted/countdown.py, reactor 5 :

class Countdown(object):
counter = 5
def count(self):
from twisted.internet import reactor
if self.counter == 0:
reactor.stop()
else:
print self.counter, '...'
self.counter -= 1
reactor.callLater(1, self.count)
from twisted.internet import reactor
reactor.callWhenRunning(Countdown().count)
print 'Start!'
reactor.run()
print 'Stop!'
API callLater callback' Twisted. callLater callback - ,
- , callback.
.

26

Twisted callback ? ,
select' ? select timeout. timeout
, select' timeout.
timeout, .
timeout , event loop 5. Twisted timeout' ,
, callback'
. - callback
, callback
. callLater
, hard realtime.
:

Start!
5 ...
4 ...
3 ...
2 ...
1 ...
Stop!
, "Stop!" , , reactor
, reactor.run.
, .

3.5

, Twisted

Twisted callback',
, , callback . . basic-twisted/exception.py
callback' ,
:

def falldown():
raise Exception('I fall down.')
def upagain():
print 'But I get up again.'
reactor.stop()
from twisted.internet import reactor
reactor.callWhenRunning(falldown)
reactor.callWhenRunning(upagain)
print 'Starting the reactor.'
reactor.run()
27

, :

Starting the reactor.


Traceback (most recent call last):
... # I removed most of the traceback
exceptions.Exception: I fall down.
But I get up again.
, callback , traceback . reactor.stop(), . reactor
, callback (
).
.
- , . , Twisted
.

3.6

Twisted. Twisted .

3.7

1. countdown.py , , .
reactor, .
2. LoopingCall twisted.internet.task. countdown LoopingCall. start stop,
deferred'. deferred' .

28

Twisted

4.1

Twisted

Twisted . , , ,
. : . , Twisted. twisted-client-1/get-poetry.py.
:

python blocking-server/slowpoetry.py --port 10000 poetry/ecstasy.txt --num-bytes 30


python blocking-server/slowpoetry.py --port 10001 poetry/fascination.txt
python blocking-server/slowpoetry.py --port 10002 poetry/science.txt
:

python twisted-client-1/get-poetry.py 10000 10001 10002


:

Task 1: got 60 bytes of poetry


Task 2: got 10 bytes of poetry
Task 3: got 10 bytes of poetry
Task 1: got 30 bytes of poetry
Task 3: got 10 bytes of poetry
Task 2: got 10 bytes of poetry
...
Task 1: 3003 bytes of poetry
Task 2: 623 bytes of poetry
Task 3: 653 bytes of poetry
Got 3 poems in 0:00:10.134220

from
from
from
from
from
from

127.0.0.1:10000
127.0.0.1:10001
127.0.0.1:10002
127.0.0.1:10000
127.0.0.1:10002
127.0.0.1:10001

, Twisted. , , . ,
. ,
, .
, , Twisted
API. Twisted ,
Twisted . , API, . , - ,
, Twisted.
Twisted PoetrySocket.
PoetrySocket , :

29

self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


self.sock.connect(address)
self.sock.setblocking(0)
, , ,
. , PoetrySocket reactor addReader:

# tell the Twisted reactor to monitor this socket for reading


from twisted.internet import reactor
reactor.addReader(self)
Twisted ,
. Twisted
callback'? Twisted ,
, Twisted , ? twisted.internet.interfaces.py, .

4.2

Twisted

Twisted , .
Interface. 8.0, Twisted
zope.interface ,
.
Interface Twisted, ,
.
- . Python
, Duck typing , ,
public , . , public (, , ...) , duck typing,
(!). , Interface -
, " ".
twisted.internet.interfaces addReader.
IReactorFDSet :

def addReader(reader):
"""
I add reader to the set of file descriptors to get read events for.
@param reader: An L{IReadDescriptor} provider that will be checked for
read events until it is removed from the reactor with
L{removeReader}.
30

@return: C{None}.
"""
IReactorFDSet - , Twisted
. , Twisted reactor addReader, . self,
public ,
self - (, self ).
.
:
1. , IReactorFDSet , ,
IReactorFDSet - .
2. .
zope.interface , ,
. ,
, .
.
3. Interface' , Python.
, , ,

, Glyph', Twisted,

.
, reader addReader
IReadDescriptor. ,
PoetrySocket .
:

class IReadDescriptor(IFileDescriptor):
def doRead():
"""
Some data is available for reading on your descriptor.
"""
1

http://glyph.twistedmatrix.com/2009/02/explaining-why-interfaces-are-great.html
31

doRead PoetrySocket. Twisted


. doRead - callback, Twisted, , doRead.
Twisted - ,
, , Interface.
callback' (, Interface') . callback'
c ,
.
callback', PoetrySocket?
, IReadDescriptor - IFileDescriptor. ,
, IReadDescriptor IFileDescriptor. , , :

class IFileDescriptor(ILoggingContext):
"""
A file descriptor.
"""
def fileno():
...
def connectionLost(reason):
...
, ,
leno , , connectionLost .
PoetrySocket .
IFileDescriptor ILoggingContext.
, ,
callback logPrex. interfaces.
, doRead , , . ? ,

Twisted, , .
, , .

4.3

callback'

Twisted . . , -

32

, Twisted, select ,
Twisted reactor.
doRead callback - callback. Twisted , , - ,
. 7:

. 7: doRead callback

, callback, , . 3, Twisted
- , .
, .
, Twisted , twisted-client-1/get-poetry-broken.py. :
1. , socket
.
2. callback doRead (
,
).
:

python twisted-client-1/get-poetry-broken.py 10000 10001 10002


:

33

Task 1: got 3003 bytes of poetry from 127.0.0.1:10000


Task 3: got 653 bytes of poetry from 127.0.0.1:10002
Task 2: got 623 bytes of poetry from 127.0.0.1:10001
Task 1: 3003 bytes of poetry
Task 2: 623 bytes of poetry
Task 3: 653 bytes of poetry
Got 3 poems in 0:00:10.132753
, , .
. recv callback', Twisted
.
, event loop
Twisted, . Twisted ,
,
. ,
os.system. , ( ), , -.
, ,
: . ,
-. ,
,
. . , ( -
), , ,
.
"" , . , ,
20 , Lisp,
,
.

4.4

Twisted . , connectionLost callback reactor , PoetrySocket'. ,

34

, , API: removeReader getReaders.


Writer API, Reader API, , ,
, . interface'
. , API, , select ( ). ,
.
, Twisted , ,
Twisted API.

4.5

1. ,
.
2. callLater, , timeout,
, .
callLater, ,
, , .

35

Twisted

5.1

, Twisted. , .
, , , . Twisted ,
, . , - ,
, .
, , . -
Twisted "win32 ,
.
- . 1.0 Twisted ,
. . ,
Twisted API, .
, . ? "" , ?
, , , .
, -
.
, API Interface'.
, Twisted . , 1.0 4 IReadDescriptor:
" , ". Twisted Interface',
, , , . , , :
Twisted , .
, Twisted , ,
. , -

36

A F, F
. , B F,
, F ( B A,
, A).
- , Twisted . ,
, Twisted .

5.2

, , Twisted, - reactor. , Twisted, , ,


, . Twisted . Twisted
", X, reactor X - " web " "
- . API, , 1.0,
.
,
( Twisted ).
, Twisted,
reactor. Twisted , API
. .
, 1.0,
, Twisted
( , ).
,
Twisted -
, . reactor .
. Twisted, Reactor,
callback'
(cooperative multi-tasking). -

37

Twisted , , . 6
, :
5 6 - .
,
Twisted.
, , : Transport, Protocol Protocol Factory.

5.3

Transport ITransport Twisted interfaces.


Twisted Transport , / . , Transport'
- TCP , . Twisted - Unix pipe's
UDP . Transport -
, .
, ITransport,
. Transport'

, callback'.
, Transport, , , .
Transport' "
, , ".
, , , .
Transport . , , Twisted ,
.

5.4

Twisted Protocol' IProtocol interfaces.


, Protocol . , Twisted Protocol

38

, FTP IMAP, , .
, , ,
.
, Twisted Protocol . , (, , ), Protocol.
Protocol ( ,
-).
Protocol ? IProtocol, makeConnection. - callback, Twisted
Transport
. Transport - , Protocol .
Twisted
.
twisted.protocols.basic. Twisted
, Protocol, ,
. , ,
,
.

5.5

Protocol,
Protocol , . Twisted , Twisted ,
Protocol " " .
Protocol - (Protocol Factory).
, Protocol Factory API IProtocolFactory, interfaces. Protocol Factory - Factory, .
buildProtocol Protocol . , Twisted ,
Protocol .

39

5.6

2.0: .0

2.0 Twisted .
twisted-client-2/get-poetry.py. , ,
. ,
.
, Twisted , .
print , ,
,
.
2.0 . socket,
socket . :

factory = PoetryClientFactory(len(addresses))
from twisted.internet import reactor
for address in addresses:
host, port = address
reactor.connectTCP(host, port, factory)
connectTCP. . - PoetryClientFactory.
- Protocol Factory ,
Twisted
PoetryProtocol .
, Factory, Protocol ,
PoetrySocket . , , Twisted
twisted.internet.protocol. Factory twisted.internet.protocol.Factory, ClientFactory,
(
, , ).
, Factory Twisted
buildProtocol.
:

def buildProtocol(self, address):


proto = ClientFactory.buildProtocol(self, address)
proto.task_num = self.task_num
self.task_num += 1
return proto
40

Protocol ? ,
protocol PoetryClientFactory:

class PoetryClientFactory(ClientFactory):
task_num = 1
protocol = PoetryProtocol # tell base class what proto to build
Factory buildProtocol
, protocol (, PoetryProtocol),
factory , ""Factory. 8:

. 8: Protocol'

, factory Protocol
, Factory,
.
, Protocol , ,
6.
, factory Protocol' Protocol Factory, protocol Factory
Protocol. , Factory
Protocol.

41

Protocol Protocol Transport, makeConnection. , Twisted . , makeConnection


Transport transport connected
Tru, 9:

. 9: Protocol Transport

, Protocol - (, , ). - dataReceived, :

def dataReceived(self, data):


self.poem += data
msg = 'Task %d: got %d bytes of poetry from %s'
print msg % (self.task_num, len(data), self.transport.getHost())
dataReceived () .
-, ,
,

42

. ,
, ,
poem.
, getHost Transport'
, . . ,
Transport ,
.
, ,
dataReceived. , 2.0,
twisted-client-2/get-poetry-stack.py.
, 2.0, , dataReceived
:

def dataReceived(self, data):


traceback.print_stack()
os._exit(0)
stack trace . :

python twisted-client-2/get-poetry-stack.py 10000


stack trace:

File "twisted-client-2/get-poetry-stack.py", line 125, in


poetry_main()
... # I removed a bunch of lines here
File ".../twisted/internet/tcp.py", line 463, in doRead # Note the doRead callback
return self.protocol.dataReceived(data)
File "twisted-client-2/get-poetry-stack.py", line 58, in dataReceived
traceback.print_stack()
doRead callback, 1.0! , Twisted , , . IReadDescriptor, Twisted, . , twisted.internet.tcp.
, ,
IWriteDescriptor ITransport. IReadDescriptor - Transport. dataReceived callback 10:
, , PoetryProtocol
PoetryClientFactory:

43

. 10: dataReceived callback

def connectionLost(self, reason):


self.poemReceived(self.poem)
def poemReceived(self, poem):
self.factory.poem_finished(self.task_num, poem)
callback connectionLost . reason - twisted.python.failure.Failure
- .
, .
factory reactor , .
, ,
- , PoetryClientFactory
. ,
, poem_nished callback :

...

self.poetry_count -= 1
if self.poetry_count == 0:
...
, -

,
lock' ,
poem_nished . ,

44

reactor ( ). : reactor
callback , .
,
1.0. callback PoetryClientFactory :

def clientConnectionFailed(self, connector, reason):


print 'Failed to connect to:', connector.getDestination()
self.poem_finished()
, callback Factory, Protocol.
Protocol , Factory
, .

5.7

, , .
. 2.1 twisted-client2/get-poetry-simple.py.

5.8

2.0 Twisted , Twisted


. , - , , - , ,
. ,
,
,
. 6 .

5.9

1. callLater , timeout ,
. loseConnection Transport ,
timeout',
timeout, .
2. stacktrace callback',
connectionLost.

45

6.1

.
(2.0) Transport, Protocol Protocol Factory.
. 2.0 ( 2.1) .
PoetryClientFactory
PoetryProtocols, , PoetryClientFactory.
, . , API:

def get_poetry(host, post):


"""Return the text of a poem from the poetry server at the given host and port."""
, . , , -
. , .
, ,
, . . Twisted
, -,
, timeout
.. , Twisted , callback',
:

def get_poetry(host, port, callback):


"""
Download a poem from the given host and port and invoke
callback(poem)
when the poem is complete.
"""
API,
Twisted, .
, ,
Twisted .
. 7 8
"Twisted "( , !),
,
.

46

6.2

3.0

3.0 twistedclient-3/get-poetry.py. get_poetry:

def get_poetry(host, port, callback):


from twisted.internet import reactor
factory = PoetryClientFactory(callback)
reactor.connectTCP(host, port, factory)
- callback'
PoetryClientFactory. factory callback :

class PoetryClientFactory(ClientFactory):
protocol = PoetryProtocol
def __init__(self, callback):
self.callback = callback
def poem_finished(self, poem):
self.callback(poem)
, factory , 2.1,
.
, . PoetryProtocol ,
2.1:

class PoetryProtocol(Protocol):
poem = ''
def dataReceived(self, data):
self.poem += data
def connectionLost(self, reason):
self.poemReceived(self.poem)
def poemReceived(self, poem):
self.factory.poem_finished(poem)
, get_poetry PoetryClientFactory
PoetryProtocol .
. main :

def poetry_main():
addresses = parse_args()
from twisted.internet import reactor
poems = []
47

def got_poem(poem):
poems.append(poem)
if len(poems) == len(addresses):
reactor.stop()
for address in addresses:
host, port = address
get_poetry(host, port, got_poem)
reactor.run()
for poem in poems:
print poem
, ,
, ( ,
Twisted).
, 3.0, . ,
, .

6.3

callback' ,
11:

. 11: callback'

11 .

48

callback', " ". Twisted, , callback'


, . , , , . ,
, callback' .
Twisted .
:
Twisted!
:
callback ,
!

, . , Twisted.
, Python - , Python - . , ,
get_poetry,
:

...
import poetrylib # I just made this module name up
poem = poetrylib.get_poetry(host, port)
...
. , ,
, , . ,
Twisted get_poetry, , callback'. ,
, .
, - .
. , import . :
.
Twisted ,
Twisted ,
. Twisted -

49

, ,
.
, , ,
Twisted . Twisted
pyGTK pyQT, python API
GUI .

6.4

3.0 ,
, 1.0. 3.0
, ,
, . clientConnectionFailed
, ClientFactory
. callback
got_poem, reactor
, , 2.
, , ?
Factory clientConnectionFailed,
. , Factory , -
, Factory . ,
( ? ). - .
, get_poetry ,
, , . , get_poetry
try/except. , . ,
,
get_poetry. :

def get_poetry(host, port, callback):


"""
Download a poem from the given host and port and invoke
callback(poem)
when the poem is complete. If there is a failure, invoke:
callback(None)
instead.
50

"""
callback' (, poem is None),
.
, , .
, None - . API None
. -, None .
, , traceback,
. , :

def get_poetry(host, port, callback):


"""
Download a poem from the given host and port and invoke
callback(poem)
when the poem is complete. If there is a failure, invoke:
callback(err)
instead, where err is an Exception instance.
"""
Exception , .
, None .
, Python',
traceback,
. Traceback' ,
.
, traceback callback', , .
Exception traceback
, (, ,
).
Twisted , Failure, Exception traceback. Failure
. Failure callback', traceback', .

51

twisted-failure/failure-examples.py ,
Failure. Failures
traceback' ,
except.
Failure. 7 ,
Twisted .
, :

def get_poetry(host, port, callback):


"""
Download a poem from the given host and port and invoke
callback(poem)
when the poem is complete. If there is a failure, invoke:
callback(err)
instead, where err is a twisted.python.failure.Failure instance.
"""
- Exception traceback
. .
, . callback - . ,
, . Python
try/exception :

try:
attempt_to_do_something_with_poetry()
except RhymeSchemeViolation:
# the code path when things go wrong
else:
# the code path when things go so, so right baby
,
.

callback:

def get_poetry(host, port, callback, errback):


"""
Download a poem from the given host and port and invoke
callback(poem)
when the poem is complete. If there is a failure, invoke:
errback(err)
instead, where err is a twisted.python.failure.Failure instance.
"""
52

6.5

3.1

API ,
. 3.1 twisted-client3/get-poetry-1.py. . PoetryClientFactory : callback errback, clientConnectionFailed:

class PoetryClientFactory(ClientFactory):
protocol = PoetryProtocol
def __init__(self, callback, errback):
self.callback = callback
self.errback = errback
def poem_finished(self, poem):
self.callback(poem)
def clientConnectionFailed(self, connector, reason):
self.errback(reason)
clientConnectionFailed Failure ( reason), ,
errback.
,
. 3.1, :

python twisted-client-3/get-poetry-1.py 10004


:

Poem failed: [Failure instance: Traceback (failure with no frames): : Connection was refused by other side: 111: Conn
]
print poem_failed errback'.
Twisted ,
traceback. traceback
, , Twisted
, .

6.6

API, Twisted , .

53

, callback' ,
Twisted.

callback'.

, API, Twisted
, callback errback?
. , Twisted ,
, .
.

6.7

1. 3.1 timeout, , .
errback .
.
2. trap Failure. except
try/except.
3. print , , clientConnectionFailed
get_poetry.

54

7.1

6 , callback'
Twisted. Twisted ,
. ,
Twisted , ,
: , .
, API get_poetry,
callback' ( callback'): -
, - . Twisted ,
callback',
, , callback',
.
, Twisted get_poetry 3.1:

...
def got_poem(poem):
print poem
reactor.stop()
def poem_failed(err):
print >>sys.stderr, 'poem download failed'
print >>sys.stderr, 'I am terribly sorry'
print >>sys.stderr, 'try again later?'
reactor.stop()
get_poetry(host, port, got_poem, poem_failed)
reactor.run()
:
1. - .
2. - .
3. .
:

...
try:
poem = get_poetry(host, port) # the synchronous version of get_poetry
except Exception, err:
55

print >>sys.stderr, 'poem download failed'


print >>sys.stderr, 'I am terribly sorry'
print >>sys.stderr, 'try again later?'
sys.exit()
else:
print poem
sys.exit()
callback else, errback except.
, errback - , callback' .
? : Python' ,
get_poetry exception, except. ,
Python', , except .
: errback poem_failed clientConnectionFailed PoetryClientFactory. ,
Python, , , - . , , errback
Failure. , callback,
.
. ( try/except), Python'
,
.
errback PoetryClientFactory, ,
, - .
, -
. , , , ,
. -
Twisted.
: else
, except ( , get_poetry
). Python'
else 27 .
Python't, !

56

, callback
errback. , - .
callback errback callback 27 .
get_poetry.
else except try/except, , callback,
errback
get_poetry. , - .
, callback'
errback'. ? , , callback' errback' ,
get_poetry,
.
: . reactor.stop
sys.exit.
:

...
try:
poem = get_poetry(host, port) # the synchronous version of get_poetry
except Exception, err:
print >>sys.stderr, 'poem download failed'
print >>sys.stderr, 'I am terribly sorry'
print >>sys.stderr, 'try again later?'
else:
print poem
sys.exit()
?
, , callback errback -
. callback',
?
, ,
callback':
1. errback' . errback' except, .
API.
2. callback'
. , callback errback .
3. callback'.

57

callback' ,
, Twisted .

7.2

Deferred

callback' , , ,
, Twisted , Deered, , callback'. Deferred twisted.internet.defer.
"deferred"() - ,
,
. , , "deferred
Deferred. , Deferred
. "" ,
" ". , .
deferred callback : , - . deferred
. , callback'
errback', deferred
( !) ( ,
). deferred callback', errback' , .
12 Deered callback errback :

58

. 12: Deferred

. deferred' reactor,
, .
, setTimeout Deferred reactor. , , ,
. , .
twisted-deferred/defer-1.py:

from twisted.internet.defer import Deferred


def got_poem(res):
print 'Your poem is served:'
print res
def poem_failed(err):
print 'No poetry for you.'
d = Deferred()
# add a callback/errback pair to the chain
d.addCallbacks(got_poem, poem_failed)
# fire the chain with a normal result
d.callback('This poem is short.')
print "Finished"
deferred, callback/errback
addCallbacks, callback. ,
:

Your poem is served:


This poem is short.
Finished
59

. , :
1. callback/errback, 3.1, callback', deferred',
, .
, deferred' callback' errback'
,
: .
2. callback' errback' deferred .
3. callback deferred ,
.
4. print', , deferred' callback' .
, reactor .
Python'.
, . twisted-deferred/defer2.py errback deferred':

from twisted.internet.defer import Deferred


from twisted.python.failure import Failure
def got_poem(res):
print 'Your poem is served:'
print res
def poem_failed(err):
print 'No poetry for you.'
d = Deferred()
# add a callback/errback pair to the chain
d.addCallbacks(got_poem, poem_failed)
# fire the chain with an error result
d.errback(Failure(Exception('I have failed.')))
print "Finished"
, :

No poetry for you.


Finished
, errback errback callback,

60

. callback', errback' .
Failure errback
, 3.1. , deferred
Exception Failure.
twisted-deferred/defer-3.py:

from twisted.internet.defer import Deferred


def got_poem(res):
print 'Your poem is served:'
print res
def poem_failed(err):
print err.__class__
print err
print 'No poetry for you.'
d = Deferred()
# add a callback/errback pair to the chain
d.addCallbacks(got_poem, poem_failed)
# fire the chain with an error result
d.errback(Exception('I have failed.'))
Exception errback. errback',
. :

twisted.python.failure.Failure
[Failure instance: Traceback (failure with no frames): : I have failed.
]
No poetry for you.
, deferred', ,
Failure . deferred ,
errback Failure.
callback, errback. , . ,
callback errback. , : , - . twisted-deferred/defer-4.py:

from twisted.internet.defer import Deferred


def out(s): print s
d = Deferred()
d.addCallbacks(out, out)
d.callback('First result')
d.callback('Second result')
print 'Finished'
61

First result
Traceback (most recent call last):
...
twisted.internet.defer.AlreadyCalledError
! deferred . , deferred , :

twisted-deferred/defer-4.py

twisted-deferred/defer-5.py

twisted-deferred/defer-6.py

twisted-deferred/defer-7.py

, print . calback errback , ,


deferred. Deferred' , .
deferred callback',
callback errback,
callback 27 . , deferred , ,
callback'.
deferred' ? twisted-deferred/defer-8.py:

import sys
from twisted.internet.defer import Deferred
def got_poem(poem):
print poem
from twisted.internet import reactor
reactor.stop()
def poem_failed(err):
print >>sys.stderr, 'poem download failed'
print >>sys.stderr, 'I am terribly sorry'
print >>sys.stderr, 'try again later?'
from twisted.internet import reactor
reactor.stop()
d = Deferred()
d.addCallbacks(got_poem, poem_failed)

62

from twisted.internet import reactor


reactor.callWhenRunning(d.callback, 'Another short poem.')
reactor.run()
- , . , callWhenRunning deferred' . , callWhenRunning
(keyword) , callback
. Twisted API, callback',
, API callback'
deferred'.
callback, errback reactor. deferred' callback' errback',
, , twisteddeferred/defer-9.py:

import sys
from twisted.internet.defer import Deferred
def got_poem(poem):
print poem
def poem_failed(err):
print >>sys.stderr, 'poem download failed'
print >>sys.stderr, 'I am terribly sorry'
print >>sys.stderr, 'try again later?'
def poem_done(_):
from twisted.internet import reactor
reactor.stop()
d = Deferred()
d.addCallbacks(got_poem, poem_failed)
d.addBoth(poem_done)
from twisted.internet import reactor
reactor.callWhenRunning(d.callback, 'Another short poem.')
reactor.run()
addBoth callback
errback. , , .
: , deferred errback .
, , deferred'.

63

7.3


callback' .
, Deferred
:
1. errback',
API. Deferred' errback'.
2. callback' , . Deferred'
,
try/except.
3. callback' . deferred', ,

.
deferred', .
,
, .

7.4

1. poem_done.
. , got_poem poem_done.
2. deferred'
errback . , errback Exception.
3. addCallback
addErrback Deferred.

64

8.1

4.0

, - deferred',
Twisted . 4.0 twisted-client-4/get-poetry.py.
get_poetry callback
errback. deferred, callback' errback'.

def get_poetry(host, port):


"""
Download a poem from the given host and port. This function
returns a Deferred which will be fired with the complete text of
the poem or a Failure if the poem could not be downloaded.
"""
d = defer.Deferred()
from twisted.internet import reactor
factory = PoetryClientFactory(d)
reactor.connectTCP(host, port, factory)
return d
factory deferred' callback/errback.
, , deferred , :

class PoetryClientFactory(ClientFactory):
protocol = PoetryProtocol
def __init__(self, deferred):
self.deferred = deferred
def poem_finished(self, poem):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.callback(poem)
def clientConnectionFailed(self, connector, reason):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.errback(reason)
, deferred
.
Twisted, , deferred .
Python'.
, PoetryProtocol, .
, - poetry_main:

65

def poetry_main():
addresses = parse_args()
from twisted.internet import reactor
poems = []
errors = []
def got_poem(poem):
poems.append(poem)
def poem_failed(err):
print >>sys.stderr, 'Poem failed:', err
errors.append(err)
def poem_done(_):
if len(poems) + len(errors) == len(addresses):
reactor.stop()
for address in addresses:
host, port = address
d = get_poetry(host, port)
d.addCallbacks(got_poem, poem_failed)
d.addBoth(poem_done)
reactor.run()
for poem in poems:
print poem
, deferred' poem_done callback' errback'.
deferred' Twisted, d deferred, . , ,
"deferred".

8.2

get_poetry
, : . , deferred. deferred -
API Twisted ,
Twited, deferred':
Deferred " " " ".
13:

66

. 13: sync async

deferred, API :
. . ,
, callback' deferred'
. , - ,
errback deferred'.
,
deferred, . ,
, deferred'.
deferred' - " "
. deferred,
, - , , , .
deferred ,
deferred' , . , deferred'.
deferred' ( , Twisted),
deferred' API,
Twisted .
deferred', Twisted Twisted ,
callback', , , .

67

8.3

deferred', callback',

Twisted, deferred', . , ,
deferred', . , , , os.system Twisted deferred
addCallback.
, Twisted
.
Twsisted deferred',
reactor, , deferred' .
, , . Twisted ,
, reactor. Deferred' - ,
Twisted
.
stack trace , callback. twisted-client-4/get-poetrystack.py . :

File "twisted-client-4/get-poetry-stack.py", line 129, in


poetry_main()
File "twisted-client-4/get-poetry-stack.py", line 122, in poetry_main
reactor.run()
... # some more Twisted function calls
protocol.connectionLost(reason)
File "twisted-client-4/get-poetry-stack.py", line 59, in connectionLost
self.poemReceived(self.poem)
File "twisted-client-4/get-poetry-stack.py", line 62, in poemReceived
self.factory.poem_finished(poem)
File "twisted-client-4/get-poetry-stack.py", line 75, in poem_finished
d.callback(poem) # here's where we fire the deferred
... # some more methods on Deferreds
File "twisted-client-4/get-poetry-stack.py", line 105, in got_poem
traceback.print_stack()
stack trace,
2.0. trace 14:

68

. 14: callback deferred'

, Twisted , . , : callback' , callback deferred' (poem_done),


callback' (got_poem).
stack trace'. , " Twisted" " " ,
deferred' - Twisted . Twisted
callback- , Twisted, Twisted .
deferred, callback-,
Twisted, . callback':
1. callback .

69

2. reactor, callback' - .
3. .
4. callback , .
callback' deferred' .
, callback, , , deferred'. deferred (d.callback), . , :
Deferred' - ( Twisted) callback'.
callback', callback' .
deferred'
callback'. twisted-deferred/deferblock.py. callback , time.sleep. print,
, callback ,
deferred'.

8.4

Deferred, " "


( callback' errback'!)
, . Deferred' Twisted,
, .
4.0 - Twisted , Twisted, deferred'
.
Twisted API, ,
, , , Twisted ,
. , Twisted.
deferred'.
, Deferred .
.

70

8.5

1. 4.0 timeout', ,
.
errback deferred', . .
2. 4.1 ,
, . , keyword-,
callback' errback'.

71

Deferred',

9.1

callback'

, callback'. deferred', ,
Twisted, Deferred
, .


callback'. , deferred' .
, . ,
, : Byronication
Engine.
, , .
, Python' :

class IByronificationEngine(Interface):
def byronificate(poem):
"""
Return a new poem like the original, but in the style of Lord Byron.
Raises GibberishError if the input is not a genuine poem.
"""
, . , , byronicate ,
, .
,
, ,
. ,
:
1. .
2. - , , .
3. ,
Byronication.

72

4. GibberishError, , .
5. - , .
6. - .
7. .
, GibberishError ,
, , .
, : . ,
- , , . , - , ,
" ".
:

try:
poem = get_poetry(host, port) # synchronous get_poetry
except:
print >>sys.stderr, 'The poem download failed.'
else:
try:
poem = engine.byronificate(poem)
except GibberishError:
print >>sys.stderr, 'The poem download failed.'
except:
print poem # handle other exceptions by using the original poem
else:
print poem
sys.exit()
, .
( deferred'), .
. , , ,
3.1, ,
deferred'. . , got_poem
callback :

def got_poem(poem):
poems.append(byron_engine.byronificate(poem))
poem_done()
73

, byronicate GibberishError
- ? 11, :
1. callback' poem_nished factory,
, callback.
2. poem_nished ,
poemReceived .
3. connectionLost .
4. Twised, .
, reactor , . , -
, . reactor
GibberishError, ,
.
, , , . got_poem
.
,
.
15, , :

. 15: C

main - " ,
, ,

74

. , main ,
, ,
(, , , - ).
, connect socket, "".
- , . , ,
. connect - , , ,
.
get_poetry . ,
( , ), ,
, .
, , connect', ,
, ,
, , - (
Python' ).
,
, , "
". " " " .

75

3.1 .
, , 16, :

. 16: callback'

: callback', (reactor)
,
. , ,
stack frame', , , , . ,
, ,
, .
Twisted , . , ( reactor
). , callback' ( deferred'),
, Twisted,
, - . ,
!
,
callback, , try/except ,
, . errback', ,
.
.

76

9.2

Deferred'

, Deferred . , deferred callback errback, , . , deferred


" " try/except, , ,
, deferred'.
deferred , ? :
( Failure) errback' .
errback, deferred,
, - ,
deferred' errback. errback , callback',
errback'e, .
12, deferred' callback'
errback' . callback/errback
0, - 1 ..
N, callback errback ( ) , errback N+1
Failure, callback N+1
.
, callback', " deferred "
". , deferred'
callback errback , (, deferred !),
deferred, . ,
, errback' deferred ( , , addErrback).
,
. errback ,
""? : .
, callback-.
N, callback, errback (, ), callback
N+1 , N, errback N+1
.
, deferred':
1. deferred callback/errback (-

77

). ,
deferred.
2. 0, callback/errback, , deferred. deferred callback,
callback 0. deferred
errback, errback 0.
3. N , errback N+1 ( Failure)
.
4. N , callback
N+1 , N+1,
.
17:

. 17: deferred'

, , callback errback
, , .

. 17 ,
deferred ,
. 18
"":

78

. 18: deferred'

18 callback deferred', callback 0. callback ,


( 0) callback'
1. callback 1 ( ), errback
2. errback "" ( ),
callback' 3.
, 17 , callback/errback
.
18, , 3 callback , ,
deferred', 3 . callback ,
, , callback ? deferred' , ,
, errback', "".
, callback' . deferred'?
. twisted-deferred/defer-unhandled.py.
deferred callback', . :

79

Finished
Unhandled error in Deferred:
Traceback (most recent call last):
...
--- <exception caught here> --...
exceptions.Exception: oops
:
1. print , .
2. , traceback , .
3. traceback' , deferred .
4. "Unhandled" "Finished".
, deferred', callback' , (, , deferred' ). , "Finish"
, "Unhandled"
, deferred . .
"",
raise . , , ,
.
, errback'. deferred
, callback/errback , :

callback/errback ,

callback/errback Failure.

errback' Failure, errback "", ,


- .

80

9.3

Callback' Errback',

- , ,
callback' errback' deferred, , .
- , deferred' callback' errback' .
4 Deered,
:
1. addCallbacks
2. addCallback
3. addErrback
4. addBoth
, . callback/errback. addCallback callback (,
) ""errback. - , .
errback' Failure, errback
errback'
.
, addErrback errback callback.
callback' Failure, callback
callback' .

9.4

Deferred

, deferred'
callback' errback'. twisted-deferred/deferred-simulator.py
python , "deferred , , deferred'
. ,
callback/errback . callback' errback'
:

( )

( )

81

( )

, , ,
,
callback errback.
, , , , . narrow ,
.
, callback ,
, - .
, ,
callback' errback'.

9.5

callback', , callback
, , callback'
. Deferred ,
, , reactor.
, ( ) .
, -,
deferred callback errback , .
, .

9.6

1. Deferred,
callback' errback'. , callback/errback.
2. deferred ,
:

deferred.addCallbacks(my_callback, my_errback)

82

deferred.addCallback(my_callback)
deferred.addErrback(my_errback)

,
.

83

10
10.1


5.0


, 9, - Cummingsier. Cummingsier
- ,
e.e.cummings. , o:

def cummingsify(poem):
return poem.lower()
, , , 5.0,
twisted-client-5/get-poetry.py,
cummingsify, :
1.
2. GibberishError
3. ValueError
, .
5.0 poetry_main:

def poetry_main():
addresses = parse_args()
from twisted.internet import reactor
poems = []
errors = []
def try_to_cummingsify(poem):
try:
return cummingsify(poem)
except GibberishError:
raise
except:
print 'Cummingsify failed!'
return poem
def got_poem(poem):
print poem
poems.append(poem)
def poem_failed(err):
print >>sys.stderr, 'The poem download failed.'
errors.append(err)
84

def poem_done(_):
if len(poems) + len(errors) == len(addresses):
reactor.stop()
for address in addresses:
host, port = address
d = get_poetry(host, port)
d.addCallback(try_to_cummingsify)
d.addCallbacks(got_poem, poem_failed)
d.addBoth(poem_done)
reactor.run()
, c ,
:
1.
2. Cummingsify failed!
3. The poem download failed.
,
5.0,
,
. ,
.
callback/errback,
Deferred', get_poetry:

. 19: deferred' 5.0

85

, pass-through errback
addCallback. pass-through Failure errback' (poem_failed). , poem_failed :
get_poetry ( deferred poem_failed deferred' errback) cummingsify.
, 19

Inkscape .
, deferred'. ,
cummingsify , 20:

. 20: deferred' 5.0

, callback' ,
callback. ,
poem_done None , got_poem
. , callback ,
got_poem , .
21 , ,
cummingsify GibberishError:
try_to_cummingsify callback
GibberishError, errback
poem_failed
(, Failure).

http://inkscape.org/
86

. 21: , GibberishError

, poem_failed ,
Failure, , , callback. , poem_failed
, None - . , , poem_failed , ,
poem_failed , err ,
errback.
, got_poem, poem_failed , poem_done errback
. , errback,
 ,
got_poem, poem_failed ,
. addBoth ,
deferred (
), addBoth nally try/except.
, 22,
, cummingsify
ValueError.
20, ,
got_poem . callback'
try_to_cummingsify, ValueError try/except .

87

. 22: , cummingsify

deferred .
, 23 - , :

. 23: ,

, poem_failed None,
callback.

88

10.2

5.1

5.0 cummingsify callback' try_to_cummingsify, try/except,


deferred' . ,
-.
, deferred'
GibberishError ValueError errback.
, errback,
: , ValueError, ,
callback , .
: errback ,
Failure ValueError,
cummingsify. , errback
, , errback .
- cummingsify
, . ,
5.1, twisted-client-5/get-poetry1.py. ValueError
CannotCummingsify,
.
cummingsify , , , , GibberishError
CannotCummingsify. , poetry_main :

def poetry_main():
addresses = parse_args()
from twisted.internet import reactor
poems = []
errors = []
def cummingsify_failed(err):
if err.check(CannotCummingsify):
print 'Cummingsify failed!'
return err.value.args[0]
return err
def got_poem(poem):
print poem
poems.append(poem)

89

def poem_failed(err):
print >>sys.stderr, 'The poem download failed.'
errors.append(err)
def poem_done(_):
if len(poems) + len(errors) == len(addresses):
reactor.stop()
for address in addresses:
host, port = address
d = get_poetry(host, port)
d.addCallback(cummingsify)
d.addErrback(cummingsify_failed)
d.addCallbacks(got_poem, poem_failed)
d.addBoth(poem_done)
deferred 24:

. 24: deferred' 5.1

cummingsify_failed errback:

def cummingsify_failed(err):
if err.check(CannotCummingsify):
print 'Cummingsify failed!'
return err.value.args[0]
return err
check Failure , Failure CannotCummingsify.

90

, ( ) , . Failure,
callback. , Failure
errback. , Failure.
25 ,
CannotCummingsify:

. 25: CannotCummingsify

, deferred',
try/except deferred' errback.

10.3

10 , Deferred
callback' errback'. ,
deferred' callback errback
.

91

, deferred', ?
! deferred' . , , 11,
Twisted .

10.4

1. 25 deferred' 5.1. .
2. deferred simulator
5.0 5.1. , , try_to_cummingsify 5.0:

r poem p
r None r None
r None r None

92

11
11.1


Twisted

c Twisted,
Twisted. Twisted, , ,
. ,
Twisted, twisted-server-1/fastpoetry.py.
fastpoetry,
, , . , , !
. ,
PoetryProtocol:

class PoetryProtocol(Protocol):
def connectionMade(self):
self.transport.write(self.factory.poem)
self.transport.loseConnection()
, Protocol
( , , ). ,
Protocol
. , ,
, connectionMade, callback'
Protocol Transport.
Transport :
(self.transport.write)
(self.transport.loseConnection). , .
, write() 
 , loseConnection() 
, ,
, .
, Protocol Factory,
, :

class PoetryFactory(ServerFactory):
protocol = PoetryProtocol
def __init__(self, poem):
self.poem = poem
93

. Factory, PoetryProtocol , ,
PoetryProtocol .
, ServerFactory ClientFactory.
, ,
ClientFactory. ? listenTCP,
, factory
ServerFactory.
main, listenTCP:

def main():
options, poetry_file = parse_args()
poem = open(poetry_file).read()
factory = PoetryFactory(poem)
from twisted.internet import reactor
port = reactor.listenTCP(options.port or 0, factory,
interface=options.iface)
print 'Serving %s on %s.' % (poetry_file, port.getHost())
reactor.run()
:
1. ,
2. PoetryFactory
3. listenTCP , Twisted,
, Factory Protocol
.
, , - .
( netcat), , .

11.2

8 9 5.
Protocol

94

Twisted . , , Twisted , . , connectTCP


listenTCP, factory.
, 9, - ,
callback connectionMade
Protocol. , . Protocol, , . ,
, shared PoetryProtocol, .
Twisted. , NetstringReceiver Protocol , netstring
Transport.
,
, . ,
listenTCP Twisted'
event loop.  (event) ,
; , ,
.
Twisted , , . (event loop), Twisted
Transport ( PoetryFactory)
PoetryProtocol . ,
Protocol , .
26.
. Transport
, 4
- select. , Transport PoetryProtocol
(,
- ,
). PoetryFactory, ,
, ,
, .
Python
, , , -

95

. 26:

. , ,
- .
, Twisted , .
, , - , ,
, .
- .
Twisted , . , Twisted

( Factory- listenTCP
). , , ,
Twisted , .
, .
, ,
. ,
, ,
Ctrl-C ( ). , , 12,
, .

96

11.3

1. Twisted,
, 2. , ,  ,
.
2.   Twisted, callLater
LoopingCall, transport.write().

--num-bytes --delay , -

. ,
, .
3. Twisted , ( ).
4.
Twisted ? ?

97

12
12.1

, Twisted , , Deferred'.
9 10 ,
. (cummingsier) , ,
, ,
. , ,
, ,   .
, 12
, , ,
, ,
,
Deferred'.

12.2


. ,
. ,
- ,
.

. :
. , : . , (Remote Procedure Call).
Twisted ,
, XML-RPC,
Perspective Broker AMP.
, , . ,
( ):

< >.< >

98

. netstring.
, netstring. netstring' ,
, , (,
). , .
, ,
.

12.3

, twisted-server-1/tranformedpoetry.py. TransformService:

class TransformService(object):
def cummingsify(self, poem):
return poem.lower()
- cummingsify, .
. :
, .
- Twisted.
.
protocol factory (
):

class TransformFactory(ServerFactory):
protocol = TransformProtocol
def __init__(self, service):
self.service = service
def transform(self, xform_name, poem):
thunk = getattr(self, 'xform_%s' % (xform_name,), None)
if thunk is None: # no such transform
return None

99

try:
return thunk(poem)
except:
return None # transform failed
def xform_cummingsify(self, poem):
return self.service.cummingsify(poem)
factory transform, protocol
. None,
,
. , TransformService, protocol factory
,
protocol.
: , xform_. , Twisted, . ,
. API, .
:

class TransformProtocol(NetstringReceiver):
def stringReceived(self, request):
if '.' not in request: # bad request
self.transport.loseConnection()
return
xform_name, poem = request.split('.', 1)
self.xformRequestReceived(xform_name, poem)
def xformRequestReceived(self, xform_name, poem):
new_poem = self.factory.transform(xform_name, poem)
if new_poem is not None:
self.sendString(new_poem)
self.transport.loseConnection()
, Twisted
netstring' NetstringReceiver.
netstring', , , - stringReceived. stringReceived
netstring', ,
, netstring ( ).

100

NetstringReceiver .
( ), ,
sendString, NetstringReceiver ( transport.write()). main,
.
, Twisted , ,
xformRequestReceived,
: .

12.4

Twisted , ,
twisted-server-1/transform-test. netcat,
( netstring). ,

11000:

python twisted-server-1/tranformedpoetry.py --port 11000


:

./twisted-server-1/transform-test 11000
:

15:here is my poem,
netstring ( ).

12.5

:
1.
2. , Twisted
3.

101

.
; , . ,
. , .
, - Twisted.
twisted.protocols.basic . -
Twisted, , ,
, , .
, , - Service ,
Twisted. , , ,
, .
Service , .
27 , ( , ):
protocol factory,
27,
protocol . (factory)
Service, Protocol
.

12.6

13, , .

102

. 27:

12.7

1. NetstringReceiver. , netstring? , netstring?


2.
protocol factory. ,
netcat
3. ,
( ).
TransformService .
4. , TransformService
(, Deferred')?
5. .
6. , netstring' .

103

13
13.1

Deferred' Deferred'

5.1 10. Deferred


callback', . 5.1, , .
,
12. : , -. , API,
, .
, callback try_to_cummingsify
Deferred.
, callback deferred' deferred? deferred  deferred',
- . , N- callback
deferred' deferred. callback :  , . deferred'
callback errback , deferred'
deferred'. , deferred ,
callback ( , ).
deferred , ? - callback/errback deferred. , deferred ,
deferred' .
deferred (, callback, deferred'), deferred N+1'
callback . deferred
( errback, deferred'), deferred
N+1' errback c failure.
,
28.
deferred 4 callback/errback.
deferred , callback deferred (). , deferred (

104

. 28: deferred'

callback/errback deferred). ,
, deferred deferred,
callback . ,
deferred deferred. , deferred ,
deferred', .
, deferred () deferred'.
, , callback deferred
28 , . ,
deferred
callback , .
29 deferred', 28, .
Deered, , , . , twisteddeferred/defer-10.py. deferred': -

105

29:

deferred'

callback', - callback', deferred. , , ,


, , , deferred
, deferred ,
, deferred .

13.2

6.0

deferred' 12. twistedclient-6/get-poetry.py. Protocol Factory


.
Protocol Factory . Protocol :

class TransformClientProtocol(NetstringReceiver):

106

def connectionMade(self):
self.sendRequest(self.factory.xform_name, self.factory.poem)
def sendRequest(self, xform_name, poem):
self.sendString(xform_name + '.' + poem)
def stringReceived(self, s):
self.transport.loseConnection()
self.poemReceived(s)
def poemReceived(self, poem):
self.factory.handlePoem(poem)
NetstringReceiver
. , ,
TransformClientFactory. , , factory .
TransformClientFactory:

class TransformClientFactory(ClientFactory):
protocol = TransformClientProtocol
def __init__(self, xform_name, poem):
self.xform_name = xform_name
self.poem = poem
self.deferred = defer.Deferred()
def handlePoem(self, poem):
d, self.deferred = self.deferred, None
d.callback(poem)
def clientConnectionLost(self, _, reason):
if self.deferred is not None:
d, self.deferred = self.deferred, None
d.errback(reason)
clientConnectionFailed = clientConnectionLost
factory ,
Protocol'. Factory Deferred, . ,
TransformClientFactory : , .
, clientConnectionLost , , ,
self.deferred None, handlePoem.
TransformClientFactory Deferred, . Twisted , :

107

, Deferred,
Deferred'.
 -  ,
deferred ,
Twisted .
TransformClientFactory, Proxy, TCP :

class TransformProxy(object):
"""
I proxy requests to a transformation service.
"""
def __init__(self, host, port):
self.host = host
self.port = port
def xform(self, xform_name, poem):
factory = TransformClientFactory(xform_name, poem)
from twisted.internet import reactor
reactor.connectTCP(self.host, self.port, factory)
return factory.deferred
xform(),
. deferred, .
, try_to_cummingsify
callback':

def try_to_cummingsify(poem):
d = proxy.xform('cummingsify', poem)
def fail(err):
print >>sys.stderr, 'Cummingsify failed!'
return poem
return d.addErrback(fail)
callback deferred,
Proxy .
try_to_cummingsify deferred' ( get_poetry), ,
.
, d.addErrback(fail).
. addCallback addErrback
deferred.
:

d.addErrback(fail)
return d
108

13.3

. , 10001, ,
10002 10003, :

python twisted-client-6/get-poetry.py 10001 10002 10003


, ,
:

python twisted-server-1/tranformedpoetry.py --port 10001


:

python twisted-server-1/fastpoetry.py --port 10002 poetry/fascination.txt


python twisted-server-1/fastpoetry.py --port 10003 poetry/science.txt
. ,
.

13.4

, deferred'
deferred' callback-, , callback'  deferred'
. ,
, , .
deferred'? !
, 14.

13.5

1. , .
2. ,
. , .
3. PoetryClientFactory deferred' 
- . get_poetry PoetryClientFactory
, .

109

4. , , , errback deferred . twisteddeferred/defer-10.py, .


5. Deferred, ,
callback/errback Deferred.

110

14
14.1

, Deferred Deferred'

Deered.
, . ,
,
. .
, .
.
, , ,
. , . 30:

. 30:

,
. , () , .
, , deferred. ,

111

, .
, - .
, ,
? Twisted ,
Deferred, : deferred , , .
, deferred , callback' errback' deferred ,
. , deferred ,
. , :
deferred callback (
errback, deferred') , , .
31, deferred, :

. 31: deferred

callback/errback ,
deferred callback,
32.
callback ( errback) , callback . ( Exception Failure),
errback.

112

. 32: deferred callback'

,
twisted-deferred/defer-11.py. ,
, deferred ,
callback'. , callback ( ,
print).
, , pause(), deferred , callback'
. callback', unpause(). ,
deferred' , callback' deferred.

14.2

1.0


twisted-server-1/poetry-proxy.py.
, , Protocol/Factory ,
, - . , .
,
ProxyService,
:

113

class ProxyService(object):
poem = None # the cached poem
def __init__(self, host, port):
self.host = host
self.port = port
def get_poem(self):
if self.poem is not None:
print 'Using cached poem.'
return self.poem
print 'Fetching poem from server.'
factory = PoetryClientFactory()
factory.deferred.addCallback(self.set_poem)
from twisted.internet import reactor
reactor.connectTCP(self.host, self.port, factory)
return factory.deferred
def set_poem(self, poem):
self.poem = poem
return poem
- get_poem. ,
. ,
, deferred, , .
get_poem - , .
, ? protocol/factory :

class PoetryProxyProtocol(Protocol):
def connectionMade(self):
d = maybeDeferred(self.factory.service.get_poem)
d.addCallback(self.transport.write)
d.addBoth(lambda r: self.transport.loseConnection())
class PoetryProxyFactory(ServerFactory):
protocol = PoetryProxyProtocol
def __init__(self, service):
self.service = service
PoetryProxyFactory :
, PoetryProxyProtocol
get_poem. PoetryProxyFactory - , . get_poem , PoetryProxyFactory twisted.internet.defer maybeDeferred.
maybeDeferred , ( ). maybeDeferred :

114

deferred, maybeDeferred
deferred

Failure, maybeDeferred deferred, ( .errback()) c


Failure

, maybeDeferred deferred, result

, maybeDeferred deferred, ( .errback())


, Failure.

, maybeDeferred
deferred', ,
, deferred. ( ,
) , deered.
1: , . deferred, , , callback'
errback', , , .
2: , , ,
deferred, maybeDeferred -
.
PoetryProxyProtocol deferred , callback',
.

14.3

, , :

python twisted-server-1/fastpoetry.py --port 10001 poetry/fascination.txt

115

python twisted-server-1/poetry-proxy.py --port 10000 10001


\e nd{verbatim}\end{scriptsize}
,
10000 10001.
:
\begin{scriptsize}\begin{verbatim}
python twisted-client-4/get-poetry.py 10000
,
. ,
, . , ,
, ,
.

14.4

2.0

, . 2.0, twisted-server-2/poetry-proxy.py. deferred' , ,


, deferred,
. get_poem
:

def get_poem(self):
if self.poem is not None:
print 'Using cached poem.'
# return an already-fired deferred
return succeed(self.poem)
print 'Fetching poem from server.'
factory = PoetryClientFactory()
factory.deferred.addCallback(self.set_poem)
from twisted.internet import reactor
reactor.connectTCP(self.host, self.port, factory)
return factory.deferred
defer.succeed - deferred . , , , ,
deferred' .callback().
deferred , defer.fail.

116

, get_poem deferred,
PoetryProxyProtocol maybeDeferred
(, , , , ):

class PoetryProxyProtocol(Protocol):
def connectionMade(self):
d = self.factory.service.get_poem()
d.addCallback(self.transport.write)
d.addBoth(lambda r: self.transport.loseConnection())

,
, .

14.5

deferred'
, , ( ) .
:

maybeDeferred ,
deferred, -
( );

deferred', defer.succeed defer.fail, 


deferred.

- . , ,
. , .
, callback'
errback' deferred', .
, 9,
twisted-deferred/defer-unhandled.py. ,   deferred' , callback
errback ,
, deferred (,
). :

117

callback/errback deferred, , , Twisted


, , , .
, , Deferred,
twisted.internet, ,
Internet.
callback'. ? Twisted. , deferred'
twisted.python. , .
deferred'? ? - . Twisted deferred', ( !). , Twisted . , Deferred
. , ,
deferred' Twisted,
.

14.6

1. twisted-deferred/defer-11.py deferred', .errback().


defer.fail.
2. , 2
,
.
3. , , , ,
. ,
.
- ,
. :
, - . , , , .
get_poem ,
deferred . deferred get_poem. ,
deferred'

118

. , .errback() deferred' .
4. -. , ,
, .
5. :

d = some_async_function() # d is a Deferred
d.addCallback(my_callback)
d.addCallback(my_other_callback)
d.addErrback(my_errback)

, deferred d 1,
. deferred',
, callback'
errback' 2-4? ?

119

15
15.1

, Twisted,
. : 
,
unittest Python'? : .
, ,
.
, Twisted , trial,
( ).
, unittest ,
( TestCase), , test, .
,
setUp tearDown, .

15.2

tests/test_poetry.py . ( PYTHONPATH)
test. ,
, ,
.
,
. , , setUp
testcase':

class PoetryTestCase(TestCase):
def setUp(self):
factory = PoetryServerFactory(TEST_POEM)
from twisted.internet import reactor
self.port = reactor.listenTCP(0, factory, interface="127.0.0.1")
self.portnum = self.port.getHost().port
setUp ,
. ,
. , ,
tearDown, :

120

def tearDown(self):
port, self.port = self.port, None
return port.stopListening()
test_client get_poetry ,
, ,
, :

def test_client(self):
"""The correct poem is returned by get_poetry."""
d = get_poetry('127.0.0.1', self.portnum)
def got_poem(poem):
self.assertEquals(poem, TEST_POEM)
d.addCallback(got_poem)
return d

, deferred. trial, callback. ,


reactor . ,
, - deferred.
trial deferred
tearDown, , deferred
(, callback/errback
). , deferred
( - 2 ). ,
, , deferred ,
callback assertEquals.
, test_failure, , get_poetry ,
:

def test_failure(self):
"""The correct failure is returned by get_poetry when
connecting to a port with no server."""
d = get_poetry('127.0.0.1', -1)
return self.assertFailure(d, ConnectionRefusedError)


assertFailure trial'.
assertRaises unittest, . deferred, ,
deferred , - .

121

, trial
:

trial tests/test_poetry.py
, testcase
OK, , .

15.3

trial unittest API, . deferred,


, trial .
deferred setUp tearDown,
.
_trial_temp, trial ,
. , , - .
33 :

. 33: trial

122

- ,
, , deferred'.
trial -   . ,
( ) , :
1.
2. , deferred
,
deferred ( , deferred).
. , , trial, , deferred'.

15.4

unit Twisted, , Twisted.


Twisted unit , . Twisted ,
,
Twisted .
16 Twisted ,
.

15.5

1. , ,
trial , .

2. Twisted .
3. .

4. Twisted .

1
2

http://twistedmatrix.com/documents/current/core/howto/testing.html
http://twistedmatrix.com/trac/browser/trunk/twisted/test
123

16

Twisted

16.1

, , , print.
, . , , :
1. ,
. , .
2. syslog.
3. , , .
4. pid ,
.
, twistd,
Twisted. , .

16.2

, twisted, Twisted, - Service. ,


Interface'.

16.2.1

IService

IService ,
.
.
: name running.
name - , 'fastpoetry', None,
. running - , true, .
IService. , , ,

124

Twisted . IService - startService stopService:

def startService():
"""
Start the service.
"""
def stopService():
"""
Stop the service.
@rtype: L{Deferred}
@return: a L{Deferred} which is triggered when the service has
finished shutting down. If shutting down is immediate, a
value can be returned (usually, C{None}).
"""

. ,
startService :

stopService :

, . ,
, Twisted ,
.
, stopService deferred, , . . ,
None deferred'.

125

, . IService,
- setServiceParent, Service :

def setServiceParent(parent):
"""
Set the parent of the service.
@type parent: L{IServiceCollection}
@raise RuntimeError: Raised if the service already has a parent
or if the service has a name and the parent already has a child
by that name.
"""
, ,
.
Interface', .

16.2.2

IServiceCollection

The IServiceCollection interface denes an object which can contain IService


objects. A service collection is a just plain container class with methods to:
IServiceCollection , IService. - :

(getServiceNamed)

(__iter__)

(addService)

(removeService)

, IServiceCollection IService,
( ).

16.2.3

Application

Twisted Application . ,
Application IService IServiceCollection,
, .
- , Twisted . ( , ..) Application.

126

, Application. Twisted
, .

16.2.4

Twisted

Twisted twisted.python.log. API , , basictwisted/log.py, Twisted.


, API , twistd .

16.3

FastPoetry 2.0

, . , twistd.
twisted-server-3/fastpoetry.py.
PoetryProtocol:

class PoetryProtocol(Protocol):
def connectionMade(self):
poem = self.factory.service.poem
log.msg('sending %d bytes of poetry to %s'
% (len(poem), self.transport.getPeer()))
self.transport.write(poem)
self.transport.loseConnection()

, print,
twisted.python.log.msg .
PoetryFactory:

class PoetryFactory(ServerFactory):
protocol = PoetryProtocol
def __init__(self, service):
self.service = service
, PoetryFactory,
,
PoetryFactory. , PoetryProtocol service
factory. , :

127

class PoetryService(service.Service):
def __init__(self, poetry_file):
self.poetry_file = poetry_file
def startService(self):
service.Service.startService(self)
self.poem = open(self.poetry_file).read()
log.msg('loaded a poem from: %s' % (self.poetry_file,))
Interface, Twisted
, ,

. twisted.application.service.Service
PoetryService.
, . , startService
. ,
( running).
. PoetryService
PoetryProtocol. ,
. , PoetryService ,
TCP . ,
, UDP XML-RPC.
, .
Twisted , ,
, (, fastpoetry.protocol fastpoetry.service).
, , .

16.3.1

Twisted tac

,
Twisted tac . tac - Twisted Application Conguration ,
twistd . , (
, ..)
. , tac (

128

), .
, tac ( tac
). , tac poetry/ecstasy.txt
10000 loopback :

# configuration parameters
port = 10000
iface = 'localhost'
poetry_file = 'poetry/ecstasy.txt'
, twistd , ,
. , twistd , .
:

# this will hold the services that combine to form the poetry server
top_service = service.MultiService()
: PoetryService, , Twisted , , .
, , MultiService -
Twisted, IService IServiceCollection.
, MultiService . , MultiService
, MultiService , , .
:

# the poetry service holds the poem. it will load the poem when it is
# started
poetry_service = PoetryService(poetry_file)
poetry_service.setServiceParent(top_service)
. PoetryService
, setServiceParent,
Twisted. TCP :

# the tcp service connects the factory to a listening socket. it will


# create the listening socket when it is started
factory = PoetryFactory(poetry_service)
tcp_service = internet.TCPServer(port, factory, interface=iface)
tcp_service.setServiceParent(top_service)
129

Twisted TCPServer
TCP , factory ( PoetryFactory). reactor.listenTCP ,
tac - . TCPServer ,
twistd.
, . , - , ,
.
,
.
, , . Application
:

# this variable has to be named 'application'


application = service.Application("fastpoetry")
# this hooks the collection we made to the application
top_service.setServiceParent(application)
, twistd
- application. , twistd ,
(
"application"). , ,
, .
34 ,
:

16.3.2

. - tac ,
twistd. , tac Python . tac twistd,
Python , :

python twisted-server-3/fastpoetry.py
, , !
, tac -
, . tac ,
.tac .py. twistd .
-, twistd:

130

. 34: fastpoetry

twistd --nodaemon --python twisted-server-3/fastpoetry.py


:

2010-06-23
2010-06-23
2010-06-23
2010-06-23
2010-06-23
2010-06-23

20:57:14-0700
20:57:14-0700
20:57:14-0700
20:57:14-0700
20:57:14-0700
20:57:14-0700

[-]
[-]
[-]
[-]
[-]
[-]

Log opened.
twistd 10.0.0 (/usr/bin/python 2.6.5) starting up.
reactor class: twisted.internet.selectreactor.SelectReactor.
__builtin__.PoetryFactory starting on 10000
Starting factory <__builtin__.PoetryFactory instance at 0x14ae8c0>
loaded a poem from: poetry/ecstasy.txt

:
1. Twisted,
log.msg PoetryFactory. logger tac
, twistd .
2. , , PoetryService
TCPServer, .
3. . ,
. , twistd
( twistd),
nodaemon, twistd
, . tac .

netcat':

131

netcat localhost 10000


,
:

2010-06-27 22:17:39-0700 [__builtin__.PoetryFactory] sending 3003 bytes of poetry to IPv4Address(TCP, '127.0.0.1', 58


log.msg PoetryProtocol.connectionMade.
, .
, Ctrl-C.
:

^C2010-06-29 21:32:59-0700 [-] Received SIGINT, shutting down.


2010-06-29 21:32:59-0700 [-] (Port 10000 Closed)
2010-06-29 21:32:59-0700 [-] Stopping factory <__builtin__.PoetryFactory instance at 0x28d38c0>
2010-06-29 21:32:59-0700 [-] Main loop terminated.
2010-06-29 21:32:59-0700 [-] Server Shut Down.
, Twisted , . ,
.
, :

twistd --nodaemon --python twisted-server-3/fastpoetry.py


twisted-intro.
twistd.pid. twistd
. :

kill `cat twistd.pid`


, twistd pid', .

16.3.3

,
, twistd :

twistd --python twisted-server-3/fastpoetry.py

132

. ,
twistd.pid, , ,  twistd.log,
, .
, twistd ,
. - 
twistd.log, ,
twistd, , ,

--logle. , twistd ,
.
, . ,
.
.
( , init), Ctrl-C. , , .
twistd.pid,
:

kill `cat twistd.pid`


,
, twistd.pid , .
twistd. , twistd
( , , ).

, , help.

16.4

Twisted

, twistd . , ,
 Python', . ,
. ,
:
1.

133

2.
3.
tac
. Twisted
.
Twisted , twistd . Twisted . , twisted .
twisted-intro. , :

...
ftp
telnet
socks
...

An FTP server.
A simple, telnet-based remote debugging service.
A SOCKSv4 proxy service.

Twisted.
, twistd.
, , help. ,
ftp:

twistd ftp --help


, help ftp, ftp, twistd.
ftp twistd ,
. , , :

twistd --nodaemon ftp --port 10001


ftp 10001. , twistd

--nodaemon

, , ,
. ,
Ctrl-C.
Ok, Twisted .
, .

134

16.4.1

IPlugin

Twisted twisted.plugin.IPlugin.
, , . IPlugin - , , - ! , twistd
. , ,
,
.
, , c ? zope.interface ,
, . plugin-
.

16.4.2

IServiceMaker

IPlugin,
IServiceMaker. , IServiceMaker, IService,
application. IServiceMaker :
1. tapname: . tap
Twisted Application Plugin. , Twisted pickled application les, taples, .
2. description: , twistd
help .
3. options: , , .
4. makeService: , IService .
,
.

16.5

Fast Poetry 3.0

Fast Poetry, twisted/plugins/fastpoetry_plugin.py.

135

,
. twistd ,
twisted/plugins ( __init__.py );
twisted/plugins PYTHONPATH, twisted . , , , ,
, .
protocol, factory
service , tac . ,
, ,
, .
:

class Options(usage.Options):
optParameters = [
['port', 'p', 10000, 'The port number to listen on.'],
['poem', None, None, 'The file containing the poem.'],
['iface', None, 'localhost', 'The interface to listen on.'],
]
, ,
twistd. , . , PoetryServiceMaker:

class PoetryServiceMaker(object):
implements(service.IServiceMaker, IPlugin)
tapname = "fastpoetry"
description = "A fast poetry service."
options = Options
def makeService(self, options):
top_service = service.MultiService()
poetry_service = PoetryService(options['poem'])
poetry_service.setServiceParent(top_service)
factory = PoetryFactory(poetry_service)
tcp_service = internet.TCPServer(int(options['port']), factory,
interface=options['iface'])
tcp_service.setServiceParent(top_service)
return top_service
zope.interface.implements , IServiceMaker

136

IPlugin. , Application,
,
application, twistd . , options ,
, , twistd.
, ,
:

service_maker = PoetryServiceMaker()
twistd
. tac , name, , . ,
IPlugin IServiceMaker.
, , .
, twisted-intro ,
PYTHONPATH. ,
twistd. , fastpoetry
.
, dropin.cache twisted/plugins. twistd .
:

twistd fastpoetry --help


, fastpoetry . , :

twistd fastpoetry --port 10000 --poem poetry/ecstasy.txt


fastpoetry . ,
twistd.pid twistd.log .
, :

kill `cat twistd.pid`


Twisted .

137

16.6

, Twisted . Twisted
twistd Twisted , tac , Twisted . 17

callback' Twisted.

16.7

1. tac
. ,
MultiService.
2. tac ,
.
3. plugin , , .
4. .

138

17
17.1

callback'

callback'.
callback' Twisted, .
x Deferred'. ,
, . , ,
, , callback'.

17.1.1

, Python' - 
, yield .
,  , , . ,
yield.
( )
.
inline-callbacks/gen-1.py:

def my_generator():
print 'starting up'
yield 1
print "workin'"
yield 2
print "still workin'"
yield 3
print 'done'
for n in my_generator():
print n
, 1,
2, 3. , , print
, print ,
.
(inline-callbacks/gen-2.py):

def my_generator():
print 'starting up'
yield 1
139

print
yield
print
yield
print

"workin'"
2
"still workin'"
3
'done'

gen = my_generator()
while True:
try:
n = gen.next()
except StopIteration:
break
else:
print n
 . :
1. - , ( next).
2. ,
( yield).
3. ( print ), .
4. , (,
).
5. , (
) , .
, callback' . , while - reactor, callback', yield, ,
callback' ,
callback'.
, ( inline-callbacks/gen-3.py), callback', , , Twisted.
, - . Callback' , . deferred',

140

callback , Python ,
Failure.
Python 2.5, , , ; inline-callbacks/gen-4.py :

class Malfunction(Exception):
pass
def my_generator():
print 'starting up'
val = yield 1
print 'got:', val
val = yield 2
print 'got:', val
try:
yield 3
except Malfunction:
print 'malfunction!'
yield 4
print 'done'
gen = my_generator()
print
print
print
print

gen.next() # start the generator


gen.send(10) # send the value 10
gen.send(20) # send the value 20
gen.throw(Malfunction()) # raise an exception inside the generator

try:
gen.next()
except StopIteration:
pass
Python 2.5 , yield - ,
. , ,
, send next ( next,
- None). ,
, throw. .

17.2

callback'

,
, callback', callback' deferred',
, . callback' yield'
yield - callback'

141

( yield ). 35 :

. 35: callback'

callback' deferred, callback


.
- , , ,
. . , ?
,
. ?
, 13, callback'
deferred' deferred'. ,
deferred , deferred
, callback ( errback)
deferred' ( ) deferred'.
, deferred
Python . ; yield , .
, deferred , ( deferred ), ( deferred ).
callback',
c inlineCallbacks
twisted.internet.defer.

142

17.2.1

inlineCallbacks

inline-callbacks/inline-callbacks-1.py:

from twisted.internet.defer import inlineCallbacks, Deferred


@inlineCallbacks
def my_callbacks():
from twisted.internet import reactor
print 'first callback'
result = yield 1 # yielded values that aren't deferred come right back
print 'second callback got', result
d = Deferred()
reactor.callLater(5, d.callback, 2)
result = yield d # yielded deferreds will pause the generator
print 'third callback got', result # the result of the deferred
d = Deferred()
reactor.callLater(5, d.errback, Exception(3))
try:
yield d
except Exception, e:
result = e
print 'fourth callback got', repr(result) # the exception from the deferred
reactor.stop()
from twisted.internet import reactor
reactor.callWhenRunning(my_callbacks)
reactor.run()
, ,
reactor.
inlineCallbacks.
-, inlineCallbacks - , , , yield. inlineCallbacks -
callback', , .
-, inlineCallbacks,
next, send throw.
,
(, ).
-, ,
deferred', , yield
.
, deferred , , deferred . deferred',

143

, yield , deferred. E deferred , yield


. , -
Exception , Failure,
try/except, yield.
callLater deferred' . callback ,
, deered,
(, get_poetry),
.
, inlineCallbacks,
'yield 1' ? - deferred.
, (
deferred'), deferred .
, , deferred',
inlineCallbacks - deferred - yield. ,
deferred', yield. , deferred
yield. , deferred
( ).
, deferred
errback , Failure.
, , ,
defer.returnValue. return, ( , ). inline-callbacks/inline-callbacks2.py .

17.3

7.0

inlineCallbacks
. twisted-client-7/get-poetry.py.
6.0 twisted-client-6/get-poetry.py. poetry_main:

def poetry_main():
addresses = parse_args()

144

xform_addr = addresses.pop(0)
proxy = TransformProxy(*xform_addr)
from twisted.internet import reactor
results = []
@defer.inlineCallbacks
def get_transformed_poem(host, port):
try:
poem = yield get_poetry(host, port)
except Exception, e:
print >>sys.stderr, 'The poem download failed:', e
raise
try:
poem = yield proxy.xform('cummingsify', poem)
except Exception:
print >>sys.stderr, 'Cummingsify failed!'
defer.returnValue(poem)
def got_poem(poem):
print poem
def poem_done(_):
results.append(_)
if len(results) == len(addresses):
reactor.stop()
for address in addresses:
host, port = address
d = get_transformed_poem(host, port)
d.addCallbacks(got_poem)
d.addBoth(poem_done)
reactor.run()
get_transformed_poem inlineCallbacks
( ). ,
( yield) deferred .
6.0, , . , try/except
.
.
:

python twisted-server-1/tranformedpoetry.py --port 10001


:

python twisted-server-1/fastpoetry.py --port 10002 poetry/fascination.txt


python twisted-server-1/fastpoetry.py --port 10003 poetry/science.txt

145

python twisted-client-7/get-poetry.py 10001 10002 10003


, ,
.

17.4

Deferred, inlineCallbacks
callback'. deferred',
inlineCallbacks . callback'
. , traceback callback', , inline-callbacks/inline-callbacks-tb.py. , traceback, reactor.run(),
callback' .
29,
callback deferred' deferred, , , inlineCallbacks deferred (
yield). 36.

146

. 36: inlineCallbacks

:
.
inlineCallbacks deferred' , ? inlineCallbacks:

callback' , .

callback' , .

callback'
.

try/except.

147

Callback' , . deferred',
,
callback' .

callback'.
, . inlineCallbacks -
.

, callback' , inlineCallbacks.

17.5

inlineCallbacks , callback'
Python .
 .

17.6

1. inlineCallbacks ?
2. inlineCallbacks
_inlineCallbacks.  .
3. callback' N yield, ,
(if )?
4. 7.0 ,
. , ? , inlineCallbacks,
, ?
5. callback got_poem 7.0 .

148

6. callback poem_done . ! , ,
reactor .
7. yield while . inlineCallbacks?

149

18
18.1

Deferred'

callback' . , deferred', .
. Twisted ,
, , -. , ,
, .
, , ,
? , ( 7.0)
. , ,
, , ,
.
, Twisted ,
,
.

18.2

DeferredList

DeferredList
Deferred deferred. , ,
( ).
.
deferred-list/deferred-list-1.py :

from twisted.internet import defer


def got_results(res):
print 'We got:', res
print 'Empty List.'
d = defer.DeferredList([])
print 'Adding Callback.'
d.addCallback(got_results)
, :

150

Empty List.
Adding Callback.
We got: []
:

DeeredList Python .
, , Deered.

DeferredList - deferred',
Deferred. , callback' errback'
, , deferred.

, callback
, DeferredList
. .

deferred - ().

deferred-list/deferred-list-2.py:

from twisted.internet import defer


def got_results(res):
print 'We got:', res
print 'One Deferred.'
d1 = defer.Deferred()
d = defer.DeferredList([d1])
print 'Adding Callback.'
d.addCallback(got_results)
print 'Firing d1.'
d1.callback('d1 result')
DeferredList . :

One Deferred.
Adding Callback.
Firing d1.
We got: [(True, 'd1 result')]
:

DeferredList callback,
deferred .

- , .

151

- , - deferred' .

deferred' ( deferred-list/deferredlist-3.py):

from twisted.internet import defer


def got_results(res):
print 'We got:', res
print 'Two Deferreds.'
d1 = defer.Deferred()
d2 = defer.Deferred()
d = defer.DeferredList([d1, d2])
print 'Adding Callback.'
d.addCallback(got_results)
print 'Firing d1.'
d1.callback('d1 result')
print 'Firing d2.'
d2.callback('d2 result')
:

Two Deferreds.
Adding Callback.
Firing d1.
Firing d2.
We got: [(True, 'd1 result'), (True, 'd2 result')]
DeferredList, , , -
deferred' , . deferred', deferred', . , DeferredList
deferred' . DeferredList,
, ,
deferred', .
? deferred-list/deferred-list-4.py:

from twisted.internet import defer


def got_results(res):
print 'We got:', res
print 'Two Deferreds.'
d1 = defer.Deferred()
d2 = defer.Deferred()
d = defer.DeferredList([d1, d2])
print 'Adding Callback.'
152

d.addCallback(got_results)
print 'Firing d2.'
d2.callback('d2 result')
print 'Firing d1.'
d1.callback('d1 result')
d2, d1. ,
deferred' d1 d2
. :

Two Deferreds.
Adding Callback.
Firing d2.
Firing d1.
We got: [(True, 'd1 result'), (True, 'd2 result')]
,
deferred', deferred'. ,
,
(, ).
, deferred' ? True?
deferred-list/deferred-list-5.py:

from twisted.internet import defer


def got_results(res):
print 'We got:', res
d1 = defer.Deferred()
d2 = defer.Deferred()
d = defer.DeferredList([d1, d2], consumeErrors=True)
d.addCallback(got_results)
print 'Firing d1.'
d1.callback('d1 result')
print 'Firing d2 with errback.'
d2.errback(Exception('d2 failure'))
d1 c , d2 . consumerErrors, ,
:

Firing d1.
Firing d2 with errback.
We got: [(True, 'd1 result'), (False, <twisted.python.failure.Failure <type 'exceptions.Exception'>>)]
d2 Failure
False - .
, DeferredList:

153

DeferredList Deferred.

DeferredList deferred, ,
deferred'.

DeferredList deferred' .

deferred'
, . deferred , - (True, result), - (False, failure).

DeferredList , deferred' .

consumeErrors
DeferredList. deferred-list/deferred-list-6.py, , :

Firing d1.
Firing d2 with errback.
We got: [(True, 'd1 result'), (False, >twisted.python.failure.Failure >type 'exceptions.Exception'<<)]
Unhandled error in Deferred:
Traceback (most recent call last):
Failure: exceptions.Exception: d2 failure
, Unhandled error in Deferred , deferred ,
callback deferred' . ,
. ? , DeferredList, DeferredList .
, d2.
DeferredList , deferred',
, . DeferredList - callback errback deferred'. , callback ( errback) (
) . Failure errback errback, d2
.
consumeErrors=True DeferredList, errback,
DeferredList deferred', None, .
, errback d2,
deferred-list/deferred-list-7.py.

154

18.3

8.0

8.0 DeferredList , ( ).
twisted-client-8/get-poetry.py.
poetry_main. :

...
ds = []
for (host, port) in addresses:
d = get_transformed_poem(host, port)
d.addCallbacks(got_poem)
ds.append(d)
dlist = defer.DeferredList(ds, consumeErrors=True)
dlist.addCallback(lambda res : reactor.stop())
8.0 callback poem_done . , deferred,
get_transformed_poem (ds) DeferredList. DeferredList , DeferredList
callback, reactor. , DeferredList, , .

18.4

37 , DeferredList:
. DeferredList,
, , . .
Deferred,
Twisted 10.1.0.

18.5

1. DeferredList.
2. deferred-list reOnOneCallback reOnOneErrback. , ( ).

155

. 37: DeferredList'

3. DeferredList, DeferredList'?
, ?
4. 8.0 ,
, . DeferredList.
5. DeferredDict .

156

19
19.1

deferred'

Twisted Twisted . Twisted 10.1.0,


Deered,
.
, :
, . 14. ,
, :
1. .
2. .
3. , , .
, , ? , , . ,
, , . .
15, ,
.
. ,

, ,
38.
, , , ,
. , ,
.

157

. 38:

Twisted ,
Deferred, . deferred'
, , .
Twisted 10.1.0, : , .
39.

. 39: deferred',

19.2

deferred'

,
deferred'. -

158

, Twisted 10.1.0
. deferred-cancel/defer-cancel-1.py:

from twisted.internet import defer


def callback(res):
print 'callback got:', res
d = defer.Deferred()
d.addCallback(callback)
d.cancel()
print 'done'
, Deferred
cancel. deferred, callback
cancel deferred'.
:

done
Unhandled error in Deferred:
Traceback (most recent call last):
Failure: twisted.internet.defer.CancelledError:
deferred'
errback, callback . , twisted.internet.defer.CancelledError,
Exception, , deferred .
errback deferred-cancel/defer-cancel-2.py:

from twisted.internet import defer


def callback(res):
print 'callback got:', res
def errback(err):
print 'errback got:', err
d = defer.Deferred()
d.addCallbacks(callback, errback)
d.cancel()
print 'done'
:

errback got: [Failure instance: Traceback (failure with no frames):


<class 'twisted.internet.defer.CancelledError'>:]
done
errback' ,
deferred'.
deferred , deferred-cancel/defer-cancel-3.py:

159

from twisted.internet import defer


def callback(res):
print 'callback got:', res
def errback(err):
print 'errback got:', err
d = defer.Deferred()
d.addCallbacks(callback, errback)
d.callback('result')
d.cancel()
print 'done'
deferred callback
. :

callback got: result


done
callback ( ), , cancel . , deferred'
.
deferred ,
deferred-cancel/defer-cancel-4.py?

from twisted.internet import defer


def callback(res):
print 'callback got:', res
def errback(err):
print 'errback got:', err
d = defer.Deferred()
d.addCallbacks(callback, errback)
d.cancel()
d.callback('result')
print 'done'
:

errback got: [Failure instance: Traceback (failure with no frames):


<class 'twisted.internet.defer.CancelledError'>:]
done
, , deferred. d.callback('result')
, , deferred
, errback
?

160

39. deferred' - , deferred'


- , . deferred'
 , deferred'
 . , - , Twisted
. Twisted deferred's, , Twisted
10.1.0.
, , cancel c :
1. Deferred, ,
(, deferred
),
callback errback.
2. : ,
, , .
Twisted deferred
, 1 ,
, deferred
.
, deferred,
, , (, ). deferred'
.
- . , , . . deferred - callback ,
, -
? , , , deferred? - callback'.

19.3

Deferred'

deferred-cancel/defer-cancel-5.py:

161

from twisted.internet import defer


def canceller(d):
print "I need to cancel this deferred:", d
def callback(res):
print 'callback got:', res
def errback(err):
print 'errback got:', err
d = defer.Deferred(canceller) # created by lower-level code
d.addCallbacks(callback, errback) # added by higher-level code
d.cancel()
print 'done'
, , callback (canceller),
Deferred, , . callback
- , (, deferred
, ). callback canceller -
, deferred, , deferred callback'
errback'.
:

I need to cancel this deferred: <Deferred at 0xb7669d2cL>


errback got: [Failure instance: Traceback (failure with no frames):
<class 'twisted.internet.defer.CancelledError'>:]
done
, callback canceller deferred' .
, . , canceller ,
errback. ,
deferred
( , CancelledError).
deferred-cancel/defer-cancel-6.py
deferred-cancel/defer-cancel-7.py.
,
reactor. deferred c callback' canceller,
. deferred-cancel/defer-cancel-8.py.
, , deferred' callback canceller. ,
, .
, , . , , ,

162

. deferredcancel/defer-cancel-9.py:

from twisted.internet.defer import Deferred


def send_poem(d):
print 'Sending poem'
d.callback('Once upon a midnight dreary')
def get_poem():
"""Return a poem 5 seconds later."""
from twisted.internet import reactor
d = Deferred()
reactor.callLater(5, send_poem, d)
return d
def got_poem(poem):
print 'I got a poem:', poem
def poem_error(err):
print 'get_poem failed:', err
def main():
from twisted.internet import reactor
reactor.callLater(10, reactor.stop) # stop the reactor in 10 seconds
d = get_poem()
d.addCallbacks(got_poem, poem_error)
reactor.run()
main()
get_poem, rector' callLater, , 5
get_poem. main get_poem,
callback/errback, reactor.
reactor 10 ( callLater). callback' deferred, ,
.
( ):

Sending poem
I got a poem: Once upon a midnight dreary
10 . deferred , .
deferred' 2 :

reactor.callLater(2, d.cancel) # cancel after 2 seconds


deferred-cancel/defer-cancel10.py, :

163

get_poem failed: [Failure instance: Traceback (failure with no frames):


<class 'twisted.internet.defer.CancelledError'>:]
Sending poem
, deferred'f
. 2
errback', CancelledError, . ,
5 , send_poem ( callback deferred'
).
, , deferredcancel/defer-cancel-4.py. deferred' , , .
, deferred',
callback deferred'.
callback?
callLater. callLater - , IDelayedCall, cancel, , .
deferred-cancel/defer-cancel-11.py. get_poem:

def get_poem():
"""Return a poem 5 seconds later."""
def canceler(d):
# They don't want the poem anymore, so cancel the delayed call
delayed_call.cancel()
# At this point we have three choices:
# 1. Do nothing, and the deferred will fire the errback
#
chain with CancelledError.
# 2. Fire the errback chain with a different error.
# 3. Fire the callback chain with an alternative result.
d = Deferred(canceler)
from twisted.internet import reactor
delayed_call = reactor.callLater(5, send_poem, d)
return d
,
callLater, cancel callback'.
, callback - delayed_call.cancel().
, deferred'.
:

get_poem failed: [Failure instance: Traceback (failure with no frames):


<class 'twisted.internet.defer.CancelledError'>:]

164

, deferred (,
send_poem).

19.4

3.0

, -
,
, , (, , ).
3.0 twisted-server-4/poetry-proxy.py
deferred'. PoetryProxyProtocol:

class PoetryProxyProtocol(Protocol):
def connectionMade(self):
self.deferred = self.factory.service.get_poem()
self.deferred.addCallback(self.transport.write)
self.deferred.addBoth(lambda r: self.transport.loseConnection())
def connectionLost(self, reason):
if self.deferred is not None:
deferred, self.deferred = self.deferred, None
deferred.cancel() # cancel the deferred if it hasn't fired
. :
1. deferred, get_poem ,
, .
2. deferred . , deferred'
, , , , ,
deferred' .
, deferred' .
ProxyService:

class ProxyService(object):
poem = None # the cached poem
def __init__(self, host, port):
self.host = host
self.port = port
def get_poem(self):
if self.poem is not None:
print 'Using cached poem.'
165

# return an already-fired deferred


return succeed(self.poem)
def canceler(d):
print 'Canceling poem download.'
factory.deferred = None
connector.disconnect()
print 'Fetching poem from server.'
deferred = Deferred(canceler)
deferred.addCallback(self.set_poem)
factory = PoetryClientFactory(deferred)
from twisted.internet import reactor
connector = reactor.connectTCP(self.host, self.port, factory)
return factory.deferred
def set_poem(self, poem):
self.poem = poem
return poem
.
:
1. reactor.connectTCP, IConnector.
.
2. deferred callback' canceler. callback
, connector . factory.deferred None. , factory errback deferred'   , deferred errback
CancelledError. , deferred ,
deferred c CancelledError,
.
, deferred ProxyService
PoetryClientFactory. callback canceler IConnector, ProxyService -
deferred'.
, , callback canceler
.
callback'!
.
. ,
:

python blocking-server/slowpoetry.py --port 10001 poetry/fascination.txt

166

( Twisted 10.1.0
):

python twisted-server-4/poetry-proxy.py --port 10000 10001


, , curl:

curl localhost:10000
Ctrl-C ,
curl . , ,
:

Fetching poem from server.


Canceling poem download.
,
, ,
.
, , . ,
.

19.5

, deferred' . .
13 , callback' errback',
deferred', deferred. , () deferred callback deferred'.
, deferred
, ,
, callback deferred'. ,
deferred? deferred ( ); , deferred
deferred.
deferred, , , .
.
deferred-cancel/defer-cancel-12.py:

167

from twisted.internet import defer


def cancel_outer(d):
print "outer cancel callback."
def cancel_inner(d):
print "inner cancel callback."
def first_outer_callback(res):
print 'first outer callback, returning inner deferred'
return inner_d
def second_outer_callback(res):
print 'second outer callback got:', res
def outer_errback(err):
print 'outer errback got:', err
outer_d = defer.Deferred(cancel_outer)
inner_d = defer.Deferred(cancel_inner)
outer_d.addCallback(first_outer_callback)
outer_d.addCallbacks(second_outer_callback, outer_errback)
outer_d.callback('result')
# at this point the outer deferred has fired, but is paused
# on the inner deferred.
print 'canceling outer deferred.'
outer_d.cancel()
print 'done'
deferred', ,
allback deferred. deferred, . :

first outer callback, returning inner deferred


canceling outer deferred.
inner cancel callback.
outer errback got: [Failure instance: Traceback (failure with no frames):
<class 'twisted.internet.defer.CancelledError'>:]
done
, deferred callback' cancel. ,
deferred , cancel callback, errback CancelledError ( deferred').

19.6

deferred' ,
, . , , .

168

, , - ,
deferred' . ,
, deferred' , c Twisted Twisted
10.1.0, API Twisted.
, deferred
.
- deferred
API .
,
Twisted, .
-
.

19.7

Deferred, Twisted.
Twisted ,
web . ,
, -,
Twisted. ,
Twisted.

19.8

1. , cancel l?
. .
2. Deferred, .
3. Twisted 10.10 deferred' cancel
callback'. .
4. deferred, get_poetry , .
5. , ,
deferred', deferred'. callLater,

169

, , deferred .
6. API Twisted,
.
Twisted. unit !

170

20
20.1

: Twisted Erlang

, ,
Python Twisted - ,
Twisted ,
, .
,
,
.
Twisted, Python . Twisted,
, ,
Twisted , ,
, .

Twisted. Python' . ,
. Twisted,
( -,
) . ,
,
, Twisted.
Python',
, . Twisted
.
Erlang

- -

(runtime system),
,
. ,
Erlang. , , Erlang, Twisted.
- , , Twisted,
.

http://erlang.org/

171

20.2

(callback)
6. callback 3.0, 6, -
dataReceived. callback ,
, .
, . (
),
,
. .

. 40:

, , -

dataReceived PoetryProtocol.

dataReceived

, ,
( ).
Protocol. "" ,
:

dataReceived(self,
dataReceived(self,
dataReceived(self,
dataReceived(self,
...

"When I have fears")


" that I may cease to be")
"Before my pen has glea")
"n'd my teeming brain")

172

Python', :

for data in poetry_stream(): # pseudo-code


dataReceived(data)
" "
41.

. 41:

for

while.

.
Protocol', , . ,
42.
() ( ). , ,
.

20.3
Erlang

Erlang
1

Python' -

, 80'. Python', Erlang


, -, ,

http://erlang.org/
173

. 42: ,

Prolog , Erlang . Erlang


, Erlang , .
Erlang - ,
. Erlang -
. , Erlang'
. Erlang , Erlang ( (immutable), Erlang - ). Erlang'
Erlang' , , , ).
Erlang 43.
,
- Erlang',
Python'. ,
, . Erlang
, -. , -

http://ru.wikipedia.org/wiki/Prolog
174

. 43: Erlang

, Twisted, ,
Erlang .
, 44 Erlang .

. 44: Erlang

, Erlang -
select-, Erlang
. Erlang Erlang ,
-

175

. Erlang
-, -, -.
, Erlang ,
,
. . ,
Erlang, .
Twisted , Erlang
Erlang
.

20.4

Erlang

, Erlang'.

, Twisted. ,
Erlang.
.
erlang-client-1/get-poetry. , , , Erlang.
main, , main
, Python':

main([]) ->
usage();
main(Args) ->
Addresses = parse_args(Args),
Main = self(),
[erlang:spawn_monitor(fun () -> get_poetry(TaskNum, Addr, Main) end)
|| {TaskNum, Addr} <- enumerate(Addresses)],
collect_poems(length(Addresses), []).

Prolog , Erlang' .
Python'. main , . Erlang , ,
, ,
(usage). - ,
.
Erlang ,
.

176

.
( Erlang ).

self

Erlang' , -

Erlang ( ).
main, __main__ Python'. :

[erlang:spawn_monitor(fun () -> get_poetry(TaskNum, Addr, Main) end)


|| {TaskNum, Addr} <- enumerate(Addresses)],
- Erlang' , Python'. Erlang ,
, .
(

get_poetry ),

, . ,
( , ).
main

collect_poems,
get_poetry.

,
main, Erlang, , Twisted
.

get_poetry. get_poetry. Erlang

Erlang

( ), :

get_poetry/4,

get_poetry/3

get_poetry/3, main :

get_poetry(Tasknum, Addr, Main) ->


{Host, Port} = Addr,
{ok, Socket} = gen_tcp:connect(Host, Port,
[binary, {active, false}, {packet, 0}]),
get_poetry(Tasknum, Socket, Main, []).
TCP ,

get_poetry

Twisted . , TCP

get_poetry/4, :

get_poetry(Tasknum, Socket, Main, Packets) ->


case gen_tcp:recv(Socket, 0) of
{ok, Packet} ->
177

io:format("Task ~w: got ~w bytes of poetry from ~s\n",


[Tasknum, size(Packet), peername(Socket)]),
get_poetry(Tasknum, Socket, Main, [Packet|Packets]);
{error, _} ->
Main ! {poem, list_to_binary(lists:reverse(Packets))}
end.
Erlang

PoetryProtocol

Twisted -

, , .

gen_tcp:recv

( ),
. "" Erlang , , Erlang.
TCP
( ,
Erlang). Erlang -
Erlang TCP , select-.
Erlang .
, , Erlang
. , , Erlang

. , Erlang (non-cooperative concurrency model).
,

get_poetry/4

. ,
Erlang ( , ) . Erlang Twisted . Twisted ,
(dataReceived) . Erlang

get_poetry/4 )


.
, ,

get_poetry

main.

get_poetry, .

Erlang collect_poems:

collect_poems(0, Poems) ->


[io:format("~s\n", [P]) || P <- Poems];
collect_poems(N, Poems) ->
178

receive
{'DOWN', _, _, _, _} ->
collect_poems(N-1, Poems);
{poem, Poem} ->
collect_poems(N, [Poem|Poems])
end.

get_poetry,
. . receive
main ,

, , (mailbox).

collect_poems

: -

DOWN. DOWN - , -

get_poetry spawn_monitor ). -

main,
(

"DOWN", , .
-

get_poetry

, -

.
, Erlang . :

python blocking-server/slowpoetry.py --port 10001 poetry/fascination.txt


python blocking-server/slowpoetry.py --port 10002 poetry/science.txt
python blocking-server/slowpoetry.py --port 10003 poetry/ecstasy.txt --num-bytes 30
Erlang ,
, Python . Linux UNIX- ,
(, Erlang

PATH ).

Windows

escript c Erlang
( Erlang ).

./erlang-client-1/get-poetry 10001 10002 10003


:

Task 3: got 30 bytes of poetry from 127:0:0:1:10003


Task 2: got 10 bytes of poetry from 127:0:0:1:10002
Task 1: got 10 bytes of poetry from 127:0:0:1:10001
...
Python ,
. ,

179

. 45: Erlang

. ,
, .
45

get_poetry

) main . , main .
, ? :

./erlang-client-1/get-poetry 10001 10005


(,
), - (,
10005).
:

Task 1: got 10 bytes of poetry from 127:0:0:1:10001


=ERROR REPORT==== 25-Sep-2010::21:02:10 ===
Error in process <0.33.0> with exit value: {{badmatch,{error,econnrefused}},[{erl_eval,expr,3}]}
Task 1: got 10 bytes of poetry from 127:0:0:1:10001
Task 1: got 10 bytes of poetry from 127:0:0:1:10001
...
, . main ,
? - .
,

get_poetry

(connection refused) (ok, Socket).

180

, Erlang
.
Erlang , ,
. main,

get_poetry , DOWN-

, . , ,
.

20.5

Twisted Erlang :
1. ( )
.
2. , , .
3. ,
.
4. ""( Python , Erlang
) .
5. , , .
, main
. Twisted Deferred, Erlang
(inter-process messages).
, . : , deferred',
callback' ; . , , .
reactor Erlang
. Erlang , :

181

1. - ( , , ).
2. .
Erlang
, (
).
Erlang, . Erlang

gen_server

- ,

, callback, , Erlang .
, Twisted, Erlang
, , .

20.6

Twisted
Erlang, .
Erlang - . Erlang
, (supervisors)
(workers) . , - ( - ).
Erlang',
Erlang', :

Programming Erlang . Erlang'.


.

Erlang Programming . .

Erlang and OTP in Action . , . , , OTP:


Erlang .

http://www.amazon.com/exec/obidos/ASIN/193435600X/krondonet-20
http://www.amazon.com/exec/obidos/ASIN/0596518188/krondonet-20
3 http://www.amazon.com/exec/obidos/ASIN/1933988789/krondonet-20
1
2

182

Erlang'.
Haskell, , Python' Erlang'. , -
.

20.7

1. Erlang Python ,
, . (, )?
2. Erlang ,
(
).
3. Erlang , ,
.
4. Erlang ,
, .
5. Erlang ,
, .
6. Erlang , Twisted.

183

21
21.1

Twisted Haskell

Twisted Erlang', , .
, -
-
Erlang.

Haskell ,
, Erlang' (, , Python'). , ,
, -.

21.2

Erlang ,
. Haskell
- ,

, . : . ( Erlang'), Haskell

. - , - .
.
, , , (), . ,
, , .
Haskell',

[1,2,3]

http://haskell.org/
http://en.wikipedia.org/wiki/Category_theory
3 http://en.wikipedia.org/wiki/Functor
4 http://en.wikipedia.org/wiki/Monad_%28category_theory%29
5 http://en.wikipedia.org/wiki/Lazy_evaluation
2

184

(Haskell Python

):

head,

head [1,2,3]
GHC Haskell, :

[~] ghci
GHCi, version 6.12.1: http://www.haskell.org/ghc/
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> head [1,2,3]
1
Prelude>

: ? for help

, , - 1.
Haskell . , [2,4 ..]
- , 2. ?
. Haskell [2,4 ..]
() .

Prelude> [2,4 ..]


[2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,
32,34,36,38,40,42,44,46,48,50,52,54,56,58,
60,62,64,66,68,70,72,74,76,78,80,82,84,86,
88,90,92,94,96,98,100,102,104,106,108,110,
...
Ctrl-C , ,
. ,
Haskell:

Prelude> head [2,4 ..]


2
Prelude> head (tail [2,4 ..])
4
Prelude> head (tail (tail [2,4 ..]))
6
, .
. ,
( ),
head, Haskell
, , head .
, .

185

tail, Haskell , , . ,
() .
Haskell,
:

Prelude>
Prelude>
Prelude>
Prelude>
(3,6,9)

let x = [1..]
let y = [2,4 ..]
let z = [3,6 ..]
head (tail (tail (zip3 x y z)))

, .
, Haskell
, , . Haskell'
46:

. 46: Haskell,

Haskell ,
(, ,
, GHC Haskell). ,
, ,
.
- .
: " ,
". : " ,
". ,
, -.
,
-.
,
,
.

186

Haskell,
Erlang, -
. ,
Haskell.

21.3

Haskell

Haskell' haskell-client1/get-poetry.hs. Erlang,


, , .
Haskell ,
Haskell, Erlang,
Haskell ,
. - runTask, getPoetry .
. Haskell,
Python' Erlang', .
, Haskell ( ,
). IO ( ), Haskell
(, , -)
.

getPoetry

poem <- hGetContents h


handle' (,
TCP ) . Haskell, , .
Haskell' ,
- select-, -.
, - , " "gotLine,
.
callback-, - . gotLine
, Haskell . , ,
Haskell . :

187

python blocking-server/slowpoetry.py --port 10001 poetry/fascination.txt


python blocking-server/slowpoetry.py --port 10002 poetry/science.txt
python blocking-server/slowpoetry.py --port 10003 poetry/ecstasy.txt --num-bytes 30
Haskell :

cd haskell-client-1/
ghc --make get-poetry.hs
get-poetry. , :

./get-poetry 10001 10002 1000


:

Task
Task
Task
Task
Task
Task
Task
Task
Task
...

3:
3:
3:
2:
3:
2:
3:
1:
1:

got
got
got
got
got
got
got
got
got

12 bytes of poetry from localhost:10003


1 bytes of poetry from localhost:10003
30 bytes of poetry from localhost:10003
20 bytes of poetry from localhost:10002
44 bytes of poetry from localhost:10003
1 bytes of poetry from localhost:10002
29 bytes of poetry from localhost:10003
36 bytes of poetry from localhost:10001
1 bytes of poetry from localhost:10001

, . . , , , .
, , , ,
.
, ,
. haskell-client2/get-poetry.hs. ,
,
.
, :

cd haskell-client-2/
ghc --make get-poetry.hs
:

./get-poetry 10001 10002 10003


188

, .
,
. ,
, , ,
.
, .
. , ,
, , ,
.
Haskell.

21.4

Twisted-Erlang-Haskell . Twisted - Twisted. Twisted ,


Python' ( Python' , ),
Twisted.
Erlang ,
,
, .
, Haskell - - , ,
, Haskell'.
,

, .
- , Real World Haskell

- , .

Learn You a Haskell .


Twisted
. ,

1
2

http://www.amazon.com/exec/obidos/ASIN/0596514980/krondonet-20
http://learnyouahaskell.com/
189

Twisted.

21.5

1. Twisted, Erlang Haskell .


2. Haskell , ,
, ,
, .
3. Haskell , Twisted.

190

22
22.1

, ,
.
Twisted.

22.2

-, .
Twisted web ,

Jean-Paul Calderone Twisted Web in 60 Seconds .


, , .

Twisted Book .
, , - Twisted. , Twisted, Twisted.

22.3

1. - Twisted.
2. Twisted .

3. Twisted

patch Twisted.

, .

22.4

http://twistedmatrix.com/trac/wiki/Documentation
http://jcalderone.livejournal.com/50562.html
3 http://www.amazon.com/gp/product/0596100329?ie=UTF8&tag=jpcalsjou20&linkCode=as2&camp=1789&creative=9325&creativeASIN=0596100329
4 http://twistedmatrix.com/trac/report
5 http://twistedmatrix.com/trac/wiki/ContributingToTwistedLabs
1
2

191

. 47:

192

Anda mungkin juga menyukai