实例解析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类方法__init__和__del__构造、析构过程分析
Mar 06 Python
python调用机器喇叭发出蜂鸣声(Beep)的方法
Mar 23 Python
理解Python中函数的参数
Apr 27 Python
Python实现代码统计工具(终极篇)
Jul 04 Python
Python中类的初始化特殊方法
Dec 01 Python
python学习入门细节知识点
Mar 29 Python
python2.6.6如何升级到python2.7.14
Apr 08 Python
Python爬取视频(其实是一篇福利)过程解析
Aug 01 Python
Python openpyxl模块原理及用法解析
Jan 19 Python
彻底搞懂 python 中文乱码问题(深入分析)
Feb 28 Python
Pycharm Available Package无法显示/安装包的问题Error Loading Package List解决
Sep 18 Python
简述python&amp;pytorch 随机种子的实现
Oct 07 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制作简单的内容采集器的原理分析
2008/10/01 PHP
php使用curl模拟登录后采集页面的例子
2013/11/04 PHP
php实现可逆加密的方法
2015/08/11 PHP
php中session_id()函数详细介绍,会话id生成过程及session id长度
2015/09/23 PHP
PHP实现批量清空删除指定文件夹所有内容的方法
2017/05/30 PHP
JQuery的Alert消息框插件使用介绍
2010/10/09 Javascript
10个基于浏览器的JavaScript调试工具分享
2013/02/07 Javascript
javascript加号&quot;+&quot;的二义性说明
2013/03/04 Javascript
jQuery 遍历-nextUntil()方法以及prevUntil()方法的使用介绍
2013/04/26 Javascript
javascript实现table表格隔行变色的方法
2015/05/13 Javascript
Javascript实现div层渐隐效果的方法
2015/05/30 Javascript
jquery彩色投票进度条简单实例演示
2020/07/23 Javascript
微信小程序 rpx 尺寸单位详细介绍
2016/10/13 Javascript
利用yarn实现一个webpack+react种子
2016/10/25 Javascript
原生js实现中奖信息无间隙滚动效果
2017/01/18 Javascript
VueJs组件prop验证简单介绍
2017/09/12 Javascript
浅谈Koa2框架利用CORS完成跨域ajax请求
2018/03/06 Javascript
解决layui上传文件提示上传异常,实际文件已经上传成功的问题
2018/08/19 Javascript
如何使用 vue + d3 画一棵树
2018/12/03 Javascript
JS+HTML实现自定义上传图片按钮并显示图片功能的方法分析
2020/02/12 Javascript
JS 5种遍历对象的方式
2020/06/16 Javascript
利用Python在一个文件的头部插入数据的实例
2018/05/02 Python
Python3利用Dlib19.7实现摄像头人脸识别的方法
2018/05/11 Python
一百行python代码将图片转成字符画
2021/02/19 Python
jupyter notebook 恢复误删单元格或者历史代码的实现
2020/04/17 Python
如何用 Python 制作一个迷宫游戏
2021/02/25 Python
佐卡伊官网:中国知名珠宝品牌
2017/02/05 全球购物
文秘自荐信
2013/10/20 职场文书
优秀毕业生推荐信
2013/11/02 职场文书
妇产医师自荐信
2014/01/29 职场文书
运动会开幕式邀请函
2014/02/03 职场文书
家长会主持词开场白
2014/03/18 职场文书
2014派出所所长群众路线对照检查材料思想汇报
2014/09/18 职场文书
首次购房证明
2015/06/19 职场文书
Python 中的单分派泛函数你真的了解吗
2021/06/22 Python
SpringDataJPA实体类关系映射配置方式
2021/12/06 Java/Android