加载中…
个人资料
麦兜搞IT
麦兜搞IT
  • 博客等级:
  • 博客积分:0
  • 博客访问:1,533,647
  • 关注人气:531
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

Twisted callback机制(转)

(2011-11-14 16:54:18)
标签:

python

deferred

twisted

it

分类: Python

看了几篇关于deferred的,这篇让我看懂了。。。。

 

http://www.douban.com/note/108289721/

最近几天在看《Python网络编程》,看到IMAP协议的时候,书中讲到了twisted,twisted的机制比较特别,在迷惑了一阵子以后我查了相关资料,详细学习了下twisted callback的机制。

在网络编程中,经常遇到的问题就是阻塞与非阻塞,阻塞就是说一个函数被调用以后,它会一直在原地等待回应,此时CPU不能做其他的事情。典型的例子有连接请求函数connect,调用connect函数以后,在服务器没有返回数据之前,connect函数是不会返回的,这个时候CPU在这个进程上面就不能做其他事情,这种情况就叫做阻塞。其他的例子也很多,比如一个数据库查询函数、I/O函数等等。这些函数有个典型的特征,就是在函数返回之前,CPU不能做其他事情,也就是说这个进程的CPU时间白白浪费在等待上面了,显然我们不喜欢这种情况,这时候就希望在这个函数没有返回之前,我们能做一些其他的事情,让CPU更好地被利用起来,这就引出了非阻塞的问题,能在自身还未返回前使CPU继续做别的事情的函数,就叫做非阻塞函数。

于是就有如下机制,我们希望一个函数在等待它想要的回应时,其他一些不相关的程序能够被执行,当回应到来的时候,系统能够以一种方法通知那个等待回应的函数,让它继续做剩下的工作。这就引出了一个经典机制,callback。
callback机制简单说起来就是,当你希望在一个函数所等待的事件(event)到来时(此时CPU在运行其他程序),系统能够以恰当的方式通知那个等待的函数,进行一些处理,那么就应该在相应的地方插入一个函数,这个函数的一个参数是callback函数的地址。那么,在特定的 event(可能是一个服务器回应,或者I/O完成的中断)到达时,系统会调用你提供的这个callback函数。非阻塞函数一般会有一个或者多个 callback function(回调函数)。这样的话,我们就可以绕过阻塞机制所带来的性能损耗,使系统的性能更好一些。

twisted中的deferred负责管理callback机制,deferred保证了程序的异步执行,有点多线程的味道,但实际上 deferred和多线程是两码事。有了deferred,即可对任务的执行进行管理控制。防止程序的运行由于等待某项任务的完成而陷入阻塞停滞,提高整体运行的效率。在用twisted编写网络服务器程序的时候,一般都是基于单线程事件处理, 那么一旦某一个连接需要大量的时间,就会影响后续的连接,从而影响了系统在单位时间的吞吐量。那么根据对非阻塞函数的想法,我们希望在一个函数调用之后能够立刻返回,不管这个函数所期待的事件是否发生,然后我们可以去执行别的程序,当这个函数期待的事件到来,能有某个东西来通知我们,这时候我们再来处理它。那么谁来通知我们呢?就是这个deferred啦。deferred究竟是一个什么玩意,如下:

1. deferred 产生的 event,是函数调用返回的对象;
2. deferred 代表一个连接任务,负责报告任务执行的延迟情况和最终结果;
3. 对deferred 的操作,通过预定的“事件响应器”(event handler)进行。

我们所调用的那个函数会返回一个deferred的实例,我们把它叫做d,这个deferred实例就是用来管理我们之前所说的callback机制,负责通知系统特定事件来了,可以继续处理剩下的部分。先来看一下代码:

代码
代码

这里为了简便起见只列出了部分关键代码,实际上这就足够了。这是一个客户端代码的片段,在上面这段代码里面connectionMade函数初始化了一个IMAPLogic类实例,IMAPLogic类在新建实例的时候首先调用了login函数,这里有一句:d=self.login(),login函数的返回值是一个deferred实例,这里的d就是我们想要的,也是关键。接下来是一连串的 addCallback和addErrback注册。表示当login函数得到了对方服务器相应后,loggedin,logout,stopreactor函数将被依次调用,我们称它为callback链。这里有一个比较特别的地方,就是在 callback链上面的一连串函数都以上一个函数的返回值作为参数来调用,在这个片段中具体来说就是login函数的返回值作为loggedin函数的参数被传入,loggedin函数的返回值作为logout函数的参数被传入,logout函数的返回值作为stopreactor函数的返回值被传入,依次一直下去,这样的话,callback链的概念就比较容易理解了。这里面有两个callErrback函数,callErrback函数是用来处理错误的,当在callback链上的某个函数发生错误时,会自动调用离它最近的callErrback函数来处理, d.addErrback(self.loginerror)表示当loggedin这个函数出错的时候,就调用
loginerror函数来处理这个错误。当错误处理完之后,继续执行下一个注册了的callback函数,也就是logout函数。另外在最后一句d.addErrback(self.errorhappened)表示,当callback链上面的所有函数出错时,都将调用 errorhappened函数,这里包括了loginerror这个错误处理函数,因此errorhappened函数可以被视为普通的错误处理函数和 “错误处理函数的错误处理函数”。twisted的callback机制可以很直观地总结如下图:

callback机制图
callback机制图

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有