实例解析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 代码效率的方法
Jul 03 Python
Python利用BeautifulSoup解析Html的方法示例
Jul 30 Python
Python利用itchat对微信中好友数据实现简单分析的方法
Nov 21 Python
python多进程实现进程间通信实例
Nov 24 Python
Python搭建FTP服务器的方法示例
Jan 19 Python
Python中一般处理中文的几种方法
Mar 06 Python
Python分布式进程中你会遇到的问题解析
May 28 Python
python 函数中的内置函数及用法详解
Jul 02 Python
Python:slice与indices的用法
Nov 25 Python
pip 20.3 新版本发布!即将抛弃 Python 2.x(推荐)
Dec 16 Python
使用python创建股票的时间序列可视化分析
Mar 03 Python
详解pytorch创建tensor函数
Mar 22 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使用PDO方法详解
2014/12/27 PHP
php二维码生成
2015/10/19 PHP
php注册和登录界面的实现案例(推荐)
2016/10/24 PHP
PHP API接口必备之输出json格式数据示例代码
2017/06/27 PHP
VSCode+PHPstudy配置PHP开发环境的步骤详解
2020/08/20 PHP
分享14个很酷的jQuery导航菜单插件
2011/04/25 Javascript
给html超链接设置事件不使用href来完成跳
2014/04/20 Javascript
将页面table内容与样式另存成excel文件的方法
2015/08/05 Javascript
JS中改变this指向的方法(call和apply、bind)
2016/03/26 Javascript
基于JS实现textarea中获取动态剩余字数的方法
2016/05/25 Javascript
常用的javascript设计模式
2017/01/11 Javascript
Vue之Watcher源码解析(2)
2017/07/19 Javascript
js禁止浏览器页面后退功能的实例(推荐)
2017/09/01 Javascript
vue中如何实现pdf文件预览的方法
2018/07/12 Javascript
如何使用Javascript中的this关键字
2020/05/28 Javascript
[01:47]2018年度DOTA2最具人气解说-完美盛典
2018/12/16 DOTA
在Python3中使用asyncio库进行快速数据抓取的教程
2015/04/02 Python
pygame学习笔记(1):矩形、圆型画图实例
2015/04/15 Python
详解Python程序与服务器连接的WSGI接口
2015/04/29 Python
python通过socket查询whois的方法
2015/07/18 Python
python学生信息管理系统(完整版)
2020/04/05 Python
pygame实现俄罗斯方块游戏(基础篇2)
2019/10/29 Python
Pytorch技巧:DataLoader的collate_fn参数使用详解
2020/01/08 Python
Python callable内置函数原理解析
2020/03/05 Python
Django 解决新建表删除后无法重新创建等问题
2020/05/21 Python
CSS3 animation实现简易幻灯片轮播特效
2016/09/27 HTML / CSS
Interhome丹麦:在线预订度假屋和公寓
2019/07/18 全球购物
.net C#面试题
2012/08/28 面试题
How TDD works
2012/09/30 面试题
四好少年事迹材料
2014/01/12 职场文书
《大自然的语言》教学反思
2014/04/08 职场文书
音乐之声音乐广播稿
2014/09/10 职场文书
医院见习报告范文
2014/11/03 职场文书
工程合作意向书范本
2015/05/09 职场文书
教师纪律作风整顿心得体会
2016/01/23 职场文书
上帝为你开了一扇窗之Tkinter常用函数详解
2021/06/02 Python