实例解析Python的Twisted框架中Deferred对象的用法


Posted in Python onMay 25, 2016

Deferred对象结构
Deferred由一系列成对的回调链组成,每一对都包含一个用于处理成功的回调(callbacks)和一个用于处理错误的回调(errbacks)。初始状态下,deffereds将由两个空回调链组成。在向其中添加回调时将总是成对添加。当异步处理中的结果返回时,Deferred将会启动并以添加时的顺序触发回调链。
用实例也许更容易说明,首先来看看addCallback:

from twisted.internet.defer import Deferred
 
def myCallback(result):
  print result
 
d = Deferred()
d.addCallback(myCallback)
d.callback("Triggering callback.")

运行它将会得到如下结果:

Triggering callback.

上例中创建了一个deffered并利用其addCallback方法注册一个用于处理成功的回调。d.callback会启动deffered并调用callback链。传入callback的参数也会被各callback链中的第一个函数接收到。
有addCallback,那另一个错误的分支,我想也能猜测到了那就是addErrorback,同样来看个例子:

from twisted.internet.defer import Deferred
 
def myErrback(failure):
  print failure
 
d = Deferred()
d.addErrback(myErrback)
d.errback(ValueError("Triggering errback."))

运行它将会得到如下结果:

[Failure instance: Traceback (failure with no frames): <type 'exceptions.ValueError'>: Triggering errback.]

可以看出Twisted会把错误封装在Failure里。
值得注意的是,在之前提到过注册回调总是成对的。在使用d.addCallback和d.addErrorback方法时,我们看似只是添加了一个callback或一个errback。而实际上,为了完成这一级回调链的创建,这些方法还会为另一半注册一个pass-through。要记住,回调链总是具有相同的长度。如果要分别指定这一级回调的callback和errback。可以使用d.addCallbacks方法:
d = Deferred()
d.addCallbacks(myCallback, myErrback)
d.callback("Triggering callback.")
那么...今天就先到这里。

进阶示例
接下来就应该来点更为实际的,那就是放进Reactor。先来看一个例子:

from twisted.internet import reactor, defer
 
class HeadlineRetriever(object):
  def processHeadline(self, headline):
    if len(headline) > 50:
      self.d.errback(Exception("The headline ``%s'' is too long!" % (headline,)))
    else:
      self.d.callback(headline)
 
  def _toHTML(self, result):
    return "<h1>%s</h1>" % (result,)
 
  def getHeadline(self, input):
    self.d = defer.Deferred()
    reactor.callLater(1, self.processHeadline, input)
    self.d.addCallback(self._toHTML)
    return self.d
 
def printData(result):
  print result
  reactor.stop()
 
def printError(failure):
  print failure
  reactor.stop()
 
h = HeadlineRetriever()
d = h.getHeadline("Breaking News: Twisted Takes us to the Moon!")
d.addCallbacks(printData, printError)
 
reactor.run()

上例接收一个标题并对其进行处理,如果标题超长会返回超长的错误,否则将其转为HTML并返回。

因所给的标题少于50个字符,故执行以上代码会得到如下返回:

<h1>Breaking News: Twisted Takes us to the Moon!</h1>

有一点值得注意的,上面用到了reactor的callLater方法,它可以用来做定时事件从而模拟一个异步的请求。

如果我们将标题变得很长,比如说:

h = HeadlineRetriever()
d = h.getHeadline("1234567890"*6)
d.addCallbacks(printData, printError)

那结果是可以遇见的:

[Failure instance: Traceback (failure with no frames): <type 'exceptions.Exception'>: The headline ``123456789012345678901234567890123456789012345678901234567890'' is too long!]

我们用图看一下触发流程:
实例解析Python的Twisted框架中Deferred对象的用法

Deferreds中的关键之处
1. Deferreds将会在调用其callback或errback时被触发;
2. Deferreds仅能被触发一次!如果尝试多次触发将会导致AlreadyCalledError异常;
3. 第N级callback或errback中的Exceptions将会传入第N+1级的errback中;如果没有errback,则会抛出Unhandled Error。如果第N级callback或errback中没有抛出Exception或返回Failure对象,那接下来将会由第N+1级中的callback进行处理;
4. callback中返回的结果将会传入下一级callback,并作为其第一个参数;
5. 如果传入errback的错误不是一个Failure对象,那将会被自动包装一次。

Python 相关文章推荐
使用python提取html文件中的特定数据的实现代码
Mar 24 Python
python进阶教程之循环对象
Aug 30 Python
python中类的属性和方法介绍
Nov 27 Python
Python网页正文转换语音文件的操作方法
Dec 09 Python
Python简易版停车管理系统
Aug 12 Python
opencv实现简单人脸识别
Feb 19 Python
浅谈Python3实现两个矩形的交并比(IoU)
Jan 18 Python
在python中利用dict转json按输入顺序输出内容方式
Feb 27 Python
python实现扫雷游戏
Mar 03 Python
python suds访问webservice服务实现
Jun 26 Python
python爬虫看看虎牙女主播中谁最“顶”步骤详解
Dec 01 Python
python glom模块的使用简介
Apr 13 Python
详解Python的Twisted框架中reactor事件管理器的用法
May 25 #Python
使用Python的Twisted框架编写非阻塞程序的代码示例
May 25 #Python
Python的Twisted框架中使用Deferred对象来管理回调函数
May 25 #Python
使用Python的Twisted框架构建非阻塞下载程序的实例教程
May 25 #Python
Python的Twisted框架上手前所必须了解的异步编程思想
May 25 #Python
Python的re模块正则表达式操作
May 25 #Python
Python的for和break循环结构中使用else语句的技巧
May 24 #Python
You might like
深入PHP中的HashTable结构详解
2013/06/13 PHP
laravel如何开启跨域功能示例详解
2017/08/31 PHP
使用js声明数组,对象在jsp页面中(获得ajax得到json数据)
2013/11/05 Javascript
js控制input框只读实现示例
2014/01/20 Javascript
JS实现简单的顶部定时关闭层效果
2014/06/15 Javascript
重写document.write实现无阻塞加载js广告(补充)
2014/12/12 Javascript
jQuery 实现侧边浮动导航菜单效果
2014/12/26 Javascript
jQuery中mouseover事件用法实例
2014/12/26 Javascript
jQuery实现可展开折叠的导航效果示例
2016/09/12 Javascript
基于JavaScript实现跳转提示页面
2016/09/24 Javascript
使用jQuery实现简单的tab框实例
2017/08/22 jQuery
深入理解vuex2.0 之 modules
2017/11/20 Javascript
详解 vue better-scroll滚动插件排坑
2018/02/08 Javascript
浅谈Postman解决token传参的问题
2018/03/31 Javascript
NodeJS安装图文教程
2018/04/19 NodeJs
微信小程序实现购物页面左右联动
2019/02/15 Javascript
ES6 proxy和reflect的使用方法与应用实例分析
2020/02/15 Javascript
python基于queue和threading实现多线程下载实例
2014/10/08 Python
Python smallseg分词用法实例分析
2015/05/28 Python
用Eclipse写python程序
2018/02/10 Python
PyTorch 对应点相乘、矩阵相乘实例
2019/12/27 Python
浅谈anaconda python 版本对应关系
2020/10/07 Python
有影响力的人、名人和艺术家的官方商品:Represent
2019/11/26 全球购物
美国手机支架公司:PopSockets
2019/11/27 全球购物
英国排名第一的冲浪店:Ann’s Cottage
2020/06/21 全球购物
JSF面试题:Jsf中导航的标签是什么
2013/04/20 面试题
TCP协议通讯的过程和步骤是什么
2015/10/18 面试题
自荐信格式范文
2013/10/07 职场文书
劳资员岗位职责
2013/11/11 职场文书
工作违纪检讨书
2014/02/17 职场文书
HR求职自荐信范文
2014/06/21 职场文书
学生会竞选演讲稿学习部
2014/08/25 职场文书
四风问题民主生活会对照检查材料思想汇报
2014/09/27 职场文书
科长个人四风问题整改措施思想汇报
2014/10/13 职场文书
Python 阶乘详解
2021/10/05 Python
python函数的两种嵌套方法使用
2022/04/02 Python