_inlineCallbacks详解

原创 2015年07月10日 21:36:01

twisted.defer的inlineCallbacks是个修饰符,其真正实现如下:

def inlineCallbacks(f):
    def unwindGenerator(*args, **kwargs):
        try:
            gen = f(*args, **kwargs)
        except _DefGen_Return:
            raise TypeError(
                "inlineCallbacks requires %r to produce a generator; instead"
                "caught returnValue being used in a non-generator" % (f,))
        if not isinstance(gen, types.GeneratorType):
            raise TypeError(
                "inlineCallbacks requires %r to produce a generator; "
                "instead got %r" % (f, gen))
        return _inlineCallbacks(None, gen, Deferred())
    return mergeFunctionMetadata(f, unwindGenerator)
实际上真正调用的是_inlineCallbacks()函数,下面是该函数的详细分析

def _inlineCallbacks(result, g, deferred):
    # waiting是用来控制递归的
    waiting = [True, # waiting for result?
                None] # result
	
    while 1:
        try:
	    # 触发下一个callback,执行结果有4种情况:
	    # 1)该callback返回一个非Deferred对象,那么回到顶部继续下一轮while,
	    #	触发下下一个callback,而该非Deferred对象作为下下一个callback的参数;
	    # 2)执行该callback时触发了一个except,执行异常处理(如果是StopIteration,
	    #	说明生成器执行完毕,不存在新的元素了);
	    # 3)该callback返回一个未执行完Deferred对象(表示该callback调用未执行完毕);
	    # 4)该callback返回一个执行完毕的Deferred对象(表示该callback调用已经执行完毕)
	    result = g.send(result)
			
	except StopIteration:
	    # fell off the end, or "return" statement
	    # deferred.callback(result=None): start processing the callback 
	    # chain starting with the provided result. 
	    # It will be send to the first callback or stored as finally one 
	    # if not any further callback has been specialed yet.
	    return deferred
	    deferred.callback(None) 
	...
		
	if isinstance(result, Deferred):
	    # a deferred was yielded, get the result.
	    def gotResult(r):
	        # 如果waiting[]为True,说明是result是个已经执行完毕的Deferred
	        # 然后gotResult()是在result.addBoth()中被调用执行的
	        # 那么通过waiting[1]保存结果,不进行递归,而是继续执行while循环
	        if waiting[]:
	            waiting[] = False
	            waiting[1] = r
	        else:
	            _inlineCallbacks(r, g, deferred)
			
	    # 当添加result Deferred对象的事件回调时,如果该result是个已经执行完毕的Deferred
	    #(Deferred对象的callback调用已经执行完毕),那么在addBoth()函数内
	    # 将直接执行事件回调函数gotResult(),并走gotResult()的if语句,然后又继续回到顶部
	    # 的while循环触发紧接着的下一个callback调用;如果该result是个未执行完毕的
	    # Deferred(Deferred对象的callback调用未执行完毕),那么添加该result的
	    # 完成触发事件gotResult,并执行result.addBoth()下面的if语句,将waiting[]修改
	    # 为False,然后执行return返回退出while循环。在接下来的时间中,
	    # 一旦该result对于的callback执行完毕,将触发该result添加的gotResult()回调,
	    # 并执行_inlineCallbacks(),然后继续执行callback链中的下一个callback调用。
	    result.addBoth(gotResult)
	    if waiting[]:
		waiting[] = False
		return deferred
			
	    # 能执行到这里,说明addBoth()中直接执行了gotResult()函数,并将保存在
	    # waiting[1]中的结果保存到result中,然后回到顶部继续执行while循环
	    result = waiting[1]
			
	    # 为下一轮while循环做准备
	    waiting[] = True
	    waiting[1] = None
			
    return deferred







理解Twisted的Deferred机制(二)使用inlineCallbacks实现类同步语法

上文提到使用deferred对象很容易陷入回调地狱中,好在python提供yield生成器语法,可以很容易就包装一套更加友好的 异步编程API。就如同ES6提供的Promise等。 目前在Twis...
  • wenxuansoft
  • wenxuansoft
  • 2016年06月20日 09:27
  • 3724

Python中的defer库

说到defer库,就必须先提到python中的一个比较特别的网络库twisted。 他与其他网络库不同的地方在于,对于很多用连接的并发,他不会使用多线程去实现。比如网络库同时发出10个请求,对于一般...
  • zzk1995
  • zzk1995
  • 2016年06月23日 23:48
  • 2039

理解Twisted与非阻塞编程

先来看一段代码:# ~*~ Twisted - A Python tale ~*~from time import sleep# Hello, I'm a developer and I mainly...
  • Q_AN1314
  • Q_AN1314
  • 2016年04月18日 12:56
  • 884

twisted学习笔记

经过上周末的突击,2dx client跑到python server前面去了:client网络连接、数据包收发、房间列表、进出房间都ok了;之前写的简易版server还只能接受连接和转发数据 故,开始...
  • xiarendeniao
  • xiarendeniao
  • 2013年10月23日 00:59
  • 5129

_inlineCallbacks详解

twisted.defer的inlineCallbacks是个修饰符,其真正实现如下: def inlineCallbacks(f): def unwindGenerator(*args, ...
  • xinghun_4
  • xinghun_4
  • 2015年07月10日 21:36
  • 1684

Scrapy阅读源码分析<四>

运行入口 还是回到最初的入口,在Scrapy源码分析(二)运行入口这篇文章中已经讲解到,在执行scrapy命令时,调用流程如下: 调用cmdline.py的execute方法调用命令实例解...
  • weixin_37947156
  • weixin_37947156
  • 2017年07月06日 12:29
  • 552

Twisted学习(三)---------------Deferred介绍

这篇教程介绍Deferreds,它是Twisted用于控制异步代码执行流程的机制。如果你不知道这意味着什么,不要着急-------这正是我要讲述的。 这篇教程关注那些刚刚要使用Twisted的人们,主...
  • happyAnger6
  • happyAnger6
  • 2016年11月20日 22:18
  • 833

inlineCallbacks: A New Way towards Asynchronous Programming

异步编程,是目前解决性能问题的一个大方向。其中怎么样实现异步有多种不同的实现方式。通过异步的方式,能够实现更高的资源利用和响应性。在网络和图形界面编程里面,一种非常普遍的做法是基于事件来实现用户响应性...
  • xinghun_4
  • xinghun_4
  • 2015年07月05日 10:57
  • 851

Scrapy Pipeline之使用REST API

REST是一种用来创建现代web应用的一系列技术的集合。它最主要的优势就是它比SOAP或者其他一些专有的web服务机制要更加简单、更加地轻量级。软件设计者们观察到了在web服务经常提供的CRUD(Cr...
  • Q_AN1314
  • Q_AN1314
  • 2016年04月19日 14:28
  • 1751

Python异步并发框架

Python 开源异步并发框架的未来 python  python3.x  gevent  tornado  async   fantix 2014年04月16日发布 ...
  • screaming
  • screaming
  • 2016年05月11日 20:14
  • 11671
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:_inlineCallbacks详解
举报原因:
原因补充:

(最多只允许输入30个字)