defer03.py
from twisted.internet import protocol, reactor, defer
from twisted.protocols import basic
class FingerProtocol(basic.LineReceiver):
def lineReceived(self, user):
d = self.factory.getUser(user)
def onError(err):
return 'Internal error in server'
d.addErrback(onError)
def writeResponse(message):
self.transport.write(message + '\r\n')
self.transport.loseConnection()
d.addCallback(writeResponse)
class FingerFactory(protocol.ServerFactory):
protocol = FingerProtocol
def __init__(self, **kwargs):
self.users = kwargs
def getUser(self, user):
return defer.succeed(self.users.get(user, "No such user")) #succeed: Return a Deferred that has already had .callback(result) called.
reactor.listenTCP(1079, FingerFactory(moshez='Happy and well'))
reactor.run()
这个实例完全和前面的finger07.py是一样的,只是添加了一个defer。这里最主要的是defer的属性是如何传递的。
从前面一个章节我们了解到,要使用回调,必须先定义defer.Deferred()。只有这样我们才能使用callback和addcallback的方法。
但是是上面的实列我们并没有发现defer.Deferred()。这是为什么呢?
下面的这个列子会说明一切
>>>from twisted.internet import defer
>>> dir(defer.succeed)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>> dir(defer.succeed(3*3))
['__doc__', '__init__', '__module__', '__repr__', '__str__', '_canceller', '_chainedTo', '_continuation', '_debugInfo', '_runCallbacks', '_runningCallbacks', '_startRunCallbacks', '_suppressAlreadyCalled', 'addBoth', 'addCallback', 'addCallbacks', 'addErrback', 'callback', 'callbacks', 'called', 'cancel', 'chainDeferred', 'debug', 'errback', 'pause', 'paused', 'result', 'unpause']
defer.succeed 本来并没有回调的方法,但是当它对一个对象执行成功后,回调的方法就有了,这就是上面的代码为什么能使用回调的关键。
defer04.py
from twisted.internet import protocol, reactor, defer, utils
from twisted.protocols import basic
class FingerProtocol(basic.LineReceiver):
def lineReceived(self, user):
d = self.factory.getUser(user) #这里就等同于d=utils.getProcessOutput("ls", [user])
def onError(err): #参数错误时调用
return 'Internal error in server'
d.addErrback(onError) #加入回调队列。
def writeResponse(message): #参数正确时调用
self.transport.write(message + '\r\n')
self.transport.loseConnection()
d.addCallback(writeResponse) #加入回调队列,回调结果
class FingerFactory(protocol.ServerFactory):
protocol = FingerProtocol
def getUser(self, user):
return utils.getProcessOutput("ls", [user]) # 返回命令组合,其实我们这里返回的是一个类似于<Deferred at 0x1537290>的结果,我们需要用函数来调出这个结果,工厂封装的协议可以帮助我们完成这个任务
reactor.listenTCP(1079, FingerFactory())
reactor.run()
这个代码其实和上面代码类似,也是通过同一样的方法获取回调属性。说明如下。
>>> from twisted.internet import protocol, reactor, defer, utils
>>> dir(utils.getProcessOutput)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>> dir(utils.getProcessOutput('ls','-alrt'))
['__doc__', '__init__', '__module__', '__repr__', '__str__', '_canceller', '_chainedTo', '_continuation', '_debugInfo', '_runCallbacks', '_runningCallbacks', '_startRunCallbacks', '_suppressAlreadyCalled', 'addBoth', 'addCallback', 'addCallbacks', 'addErrback', 'callback', 'callbacks', 'called', 'cancel', 'chainDeferred', 'debug', 'errback', 'pause', 'paused', 'unpause']
我们来测试下这个代码
客户端:
[root@localhost ~]# telnet 127.0.0.1 1079 #连接到端口
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
-l #输入-l 组合命令
total 28 #得到服务端的结果,服务端返回
-rw-r--r--. 1 root root 807 Aug 13 18:09 defer.py
-rw-r--r--. 1 root root 2137 May 19 22:16 echoserver.py
-rw-r--r--. 1 root root 422 May 20 01:59 stu_01.py
-rw-r--r--. 1 root root 496 May 20 02:00 stu_02.py
-rw-r--r--. 1 root root 604 May 20 02:22 stu_03.py
-rw-r--r--. 1 root root 834 May 20 02:49 stu_04.py
-rw-r--r--. 1 root root 368 Aug 12 16:57 test.py
Connection closed by foreign host. #断开链接
[root@localhost ~]#
大家一定要记住流程。
函数绑定deferred,函数释放deferred。