• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell
您的位置:首页 > 脚本语言 >python > Python的Twisted框架中使用Deferred对象来管理回调函数

Python的Twisted框架中使用Deferred对象来管理回调函数

作者: 字体:[增加 减小] 来源:互联网

通过本文主要向大家介绍了python twisted,python twisted下载,python twisted安装,twisted python3.5,twisted python3等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

首先抛出我们在讨论使用回调编程时的一些观点:

  • 激活errback是非常重要的。由于errback的功能与except块相同,因此用户需要确保它们的存在。他们并不是可选项,而是必选项。
  • 不在错误的时间点激活回调与在正确的时间点激活回调同等重要。典型的用法是,callback与errback是互斥的即只能运行其中一个。
  • 使用回调函数的代码重构起来有些困难。

Deferred
Twisted使用Deferred对象来管理回调函数的序列。有些情况下可能要把一系列的函数关联到Deferred对象上,以便在在异步操作完成时按次序地调用(这些一系列的回调函数叫做回调函数链);同时还要有一些函数在异步操作出现异常时来调用。当操作完成时,会先调用第一个回调函数,或者当错误发生时,会先调用第一个错误处理回调函数,然后Deferred对象会把每个回调函数或错误处理回调函数的返回值传递给链中的下一个函数。
Callbacks
一个twisted.internet.defer.Deferred对象代表着在将来某个时刻一定会产生结果的一个函数。我们可以把一个回调函数关联到Deferred对象上,一旦这个Deferred对象有了结果,这个回调函数就会被调用。另外,Deferred对象还允许开发者为它注册一个错误处理回调函数。Deferred机制对于各种各样的阻塞或者延时操作都为开发者提供了标准化的接口。
from twisted.internet import reactor, defer

def getDummyData(inputData):
  """
  This function is a dummy which simulates a delayed result and
  returns a Deferred which will fire with that result. Don't try too
  hard to understand this.
  """
  print('getDummyData called')
  deferred = defer.Deferred()
  # simulate a delayed result by asking the reactor to fire the
  # Deferred in 2 seconds time with the result inputData * 3
  reactor.callLater(2, deferred.callback, inputData * 3)
  return deferred

def cbPrintData(result):
  """
  Data handling function to be added as a callback: handles the
  data by printing the result
  """
  print('Result received: {}'.format(result))

deferred = getDummyData(3)
deferred.addCallback(cbPrintData)

# manually set up the end of the process by asking the reactor to
# stop itself in 4 seconds time
reactor.callLater(4, reactor.stop)
# start up the Twisted reactor (event loop handler) manually
print('Starting the reactor')
reactor.run()

</div>

多个回调函数
在一个Deferred对象上可以关联多个回调函数,这个回调函数链上的第一个回调函数会以Deferred对象的结果为参数来调用,而第二个回调函数以第一个函数的结果为参数来调用,依此类推。为什么需要这样的机制呢?考虑一下这样的情况,twisted.enterprise.adbapi返回一个Deferred对象——一个一个SQL查询的结果,可能有某个web窗口会在这个Deferred对象上添加一个回调函数,以把查询结果转换成HTML的格式,然后把Deferred对象继续向前传递,这时Twisted会调用这个回调函数并把结果返回给HTTP客户端。在出现错误或者异常的情况下,回调函数链不会被调用。

from twisted.internet import reactor, defer


class Getter:
  def gotResults(self, x):
    """
    The Deferred mechanism provides a mechanism to signal error
    conditions. In this case, odd numbers are bad.

    This function demonstrates a more complex way of starting
    the callback chain by checking for expected results and
    choosing whether to fire the callback or errback chain
    """
    if self.d is None:
      print("Nowhere to put results")
      return

    d = self.d
    self.d = None
    if x % 2 == 0:
      d.callback(x * 3)
    else:
      d.errback(ValueError("You used an odd number!"))

  def _toHTML(self, r):
    """
    This function converts r to HTML.

    It is added to the callback chain by getDummyData in
    order to demonstrate how a callback passes its own result
    to the next callback
    """
    return "Result: %s" % r

  def getDummyData(self, x):
    """
    The Deferred mechanism allows for chained callbacks.
    In this example, the output of gotResults is first
    passed through _toHTML on its way to printData.

    Again this function is a dummy, simulating a delayed result
    using callLater, rather than using a real asynchronous
    setup.
    """
    self.d = defer.Deferred()
    # simulate a delayed result by asking the reactor to schedule
    # gotResults in 2 seconds time
    reactor.callLater(2, self.gotResults, x)
    self.d.addCallback(self._toHTML)
    return self.d


def cbPrintData(result):
  print(result)


def ebPrintError(failure):
  import sys
  sys.stderr.write(str(failure))


# this series of callbacks and errbacks will print an error message
g = Getter()
d = g.getDummyData(3)
d.addCallback(cbPrintData)
d.addErrback(ebPrintError)

# this series of callbacks and errbacks will print "Result: 12"
g = Getter()
d = g.getDummyData(4)
d.addCallback(cbPrintData)
d.addErrback(ebPrintError)

reactor.callLater(4, reactor.stop)
reactor.run()

</div>

需要注意的一点是,在方法gotResults中处理self.d的方式。在Deferred对象被结果或者错误激活之前,这个属性被设置成了None,这样Getter实例就不会再持有将要激活的Deferred对象的引用。这样做有几个好处,首先,这样可以避免Getter.gotResults有时会重复激活相同的Deferred对象的可能性(这样会导致出现AlreadyCalledError异常)。其次,这样做可以使得该Deferred对象上可以添加一个调用了Getter.getDummyData函数的回调函数,而不会产生问题。还有,这样使得Python垃圾收集器更容易通过引用循环来检测出一个对象是否需要回收。
可视化的解释
这里写图片描述

2016525111342144.jpg (503×187)
1.请求方法请求数据到Data Sink,得到返回的Deferred对象。
2.请求方法把回调函数关联到Deferred对象上。

2016525111420537.jpg (240×382)

1.当结果已经准备好后,把它传递给Deferred对象。如果操作成功就调用Deferred对象的.callback(result)方法,如果操作失败就调用Deferred对象的.errback(faliure)方法。注意failure是twisted.python.failure.Failure类的一个实例。
2.Deferred对象使用result或者faliure来激活之前添加的回调函数或者错误处理回调函数。然后就按照下面的规则来沿着回调函数链继续执行下去:
回调函数的结果总是当做第一个参数被传递给下一个回调函数,这样就形成了一个链式的处理器。
如果一个回调函数抛出了异常,就转到错误处理回调函数来执行。
如果一个faliure没有得到处理,那么它会沿着错误处理回调函数链一直传递下去,这有点像异步版本的except语句。
如果一个错误处理回调函数没有抛出异常或者返回一个twisted.python.failure.Failure实例,那么接下来就转到去执行回调函数。
错误处理回调函数
Deferred对象的错误处理模型是以Python的异常处理为基础的。在没有错误发生的情况下,所有的回调函数都会被执行,一个接着一个,就像上面所说的那样。
如果没有执行回调函数而是执行了错误处理回调函数(比如DB查询发生了错误),那么一个twisted.python.failure.Failure对象会被传递给第一个错误处理回调函数(你可以添加多个错误处理回调函数,就像回调函数链一样)。可以把错误处理回调函数链当做普通Python代码中的except代码块。
除非在except代码块中显式地raise了一个错误,否则Exception对象就会被捕捉到且不再继续传播下去,然后又开始正常地执行程序。对于错误处理回调函数链来说也是一样,除非你显式地return一个Faliure或者重新抛出一个异常,否则错误就会停止继续传播,然后就会从那里开始执行正常的回调函数链(使用错误处理回调函数返回的值)。如果错误处理回调函数返回了一个Faliure或者抛出了一个异常,那么这个Faliure或者异常就会被传递给下一个错误处理回调函数。
注意,如果一个错误处理回调函数什么也没有返回,那它实际上返回的是None,这就意味着在这个错误处理回调函数执行之后会继续回调函数链的执行。这可能不是你实际上期望的那样,所以要确保你的错误处理回调函数返回一个Faliure对象(或者就是传递给它当参数的那个Faliure对象)或者一个有意义的返回值以便来执行下一个回调函数。
twisted.python.failure.Failure有一个有用的方法叫做trap,可以让下面的代码变成更有效率的另一种形式:

try:
  # code that may throw an exception
  cookSpamAndEggs()
except (Spam
  


 

您可能想查找下面的文章:

  • Python 基于Twisted框架的文件夹网络传输源码
  • 剖析Python的Twisted框架的核心特性
  • 实例解析Python的Twisted框架中Deferred对象的用法
  • 详解Python的Twisted框架中reactor事件管理器的用法
  • 使用Python的Twisted框架编写非阻塞程序的代码示例
  • Python的Twisted框架中使用Deferred对象来管理回调函数
  • 使用Python的Twisted框架构建非阻塞下载程序的实例教程
  • Python的Twisted框架上手前所必须了解的异步编程思想
  • 使用Python的Treq on Twisted来进行HTTP压力测试
  • 利用Python的Twisted框架实现webshell密码扫描器的教程

相关文章

  • Python程序设计入门(1)基本语法简介
  • Python的Flask站点中集成xhEditor文本编辑器的教程
  • Python网页解析利器BeautifulSoup安装使用介绍
  • 在centos7中分布式部署pyspider
  • Python中的yield浅析
  • 详谈Python2.6和Python3.0中对除法操作的异同
  • 介绍Python的Django框架中的静态资源管理器django-pipeline
  • Python中的super用法详解
  • Python实现从URL地址提取文件名的方法
  • Python urlopen 使用小示例

文章分类

  • vbs
  • DOS/BAT
  • hta/htc
  • python
  • perl
  • VBA
  • ColdFusion
  • ruby
  • PowerShell
  • Lua
  • Golang
  • linux shell

最近更新的内容

    • python脚本爬取字体文件的实现方法
    • Python 出现错误TypeError: ‘NoneType’ object is not iterable解决办法
    • 基于Python实现一个简单的银行转账操作
    • 开始着手第一个Django项目
    • Python自定义主从分布式架构实例分析
    • Python函数中*args和**kwargs来传递变长参数的用法
    • python实现简单socket程序在两台电脑之间传输消息的方法
    • Python import用法以及与from...import的区别
    • Mac OS X10.9安装的Python2.7升级Python3.3步骤详解
    • TensorFlow——Checkpoint为模型添加检查点的实例

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有