实例解析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 相关文章推荐
Django imgareaselect手动剪切头像实现方法
May 26 Python
Python 中的Selenium异常处理实例代码
May 03 Python
Python切片索引用法示例
May 15 Python
Python中单线程、多线程和多进程的效率对比实验实例
May 14 Python
python实现随机加减法生成器
Feb 24 Python
python实现逆滤波与维纳滤波示例
Feb 26 Python
python deque模块简单使用代码实例
Mar 12 Python
python属于解释语言吗
Jun 11 Python
python 图像插值 最近邻、双线性、双三次实例
Jul 05 Python
用python实现学生管理系统
Jul 24 Python
Python wordcloud库安装方法总结
Dec 31 Python
Python初识逻辑与if语句及用法大全
Aug 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版本实现代码
2012/09/15 PHP
php生成局部唯一识别码LUID的代码
2012/10/06 PHP
PHP内置过滤器FILTER使用实例
2014/06/25 PHP
Laravel 5.5 的自定义验证对象/类示例代码详解
2017/08/29 PHP
PHP高并发和大流量解决方案整理
2019/12/24 PHP
JQuery 写的个性导航菜单
2009/12/24 Javascript
jQuery 动态云标签插件
2014/11/11 Javascript
jQuery实现简单的间隔向上滚动效果
2015/03/09 Javascript
javascript创建函数的20种方式汇总
2015/06/23 Javascript
JS实现环形进度条(从0到100%)效果
2016/07/05 Javascript
JS实现百度搜索接口及链接功能实例代码
2018/02/02 Javascript
Node.js 使用AngularJS的方法示例
2018/05/11 Javascript
jQuery 实现批量提交表格多行数据的方法
2018/08/09 jQuery
JS模拟浏览器实现全局搜索功能
2019/09/11 Javascript
JavaScript实现省份城市的三级联动
2020/02/11 Javascript
Vue移动端用淘宝弹性布局lib-flexible插件做适配的方法
2020/05/26 Javascript
详解微信小程序入门从这里出发(登录注册、开发工具、文件及结构介绍)
2020/07/21 Javascript
跟老齐学Python之复习if语句
2014/10/02 Python
Python 自动补全(vim)
2014/11/30 Python
Anaconda入门使用总结
2018/04/05 Python
DataFrame中去除指定列为空的行方法
2018/04/08 Python
python实现石头剪刀布程序
2021/01/20 Python
python 使用while写猜年龄小游戏过程解析
2019/10/07 Python
Python实现字符串中某个字母的替代功能
2019/10/21 Python
Python 爬虫实现增加播客访问量的方法实现
2019/10/31 Python
解决pycharm安装第三方库失败的问题
2020/05/09 Python
施华洛世奇水晶荷兰官方网站:SWAROVSKI荷兰
2017/05/12 全球购物
学生会主席就职演讲稿
2014/01/14 职场文书
信息管理应届生求职信
2014/03/07 职场文书
二年级学生评语大全
2014/04/23 职场文书
医院院务公开实施方案
2014/05/03 职场文书
感恩母亲节演讲稿
2014/05/07 职场文书
优秀大学生事迹材料
2014/12/24 职场文书
个人自荐书怎么写
2015/03/26 职场文书
忘记Grafana不要紧2种Grafana重置admin密码方法详细步骤
2022/04/07 Servers
win sever 2022如何占用操作主机角色
2022/06/25 Servers