twisted学习-4 defer异步回调

本文深入解析了Twisted框架中defer的概念及其在实现回调机制中的作用。通过示例代码,详细展示了如何在不同场景下利用defer来处理异步操作,并解释了为何在某些情况下看似未直接创建Deferred对象却仍能触发回调。同时,通过对比不同方法的使用,阐述了在实际编程中灵活运用defer的重要性。

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


转载于:https://my.oschina.net/jastme/blog/300941

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值