1.gen.coroutine的作用

自动执行生成器

2.Future对象

在介绍异步使用之前,先了解一下Future对象的作用。

Future简单可以理解为一个占位符,将来会执行的对象,类似javascript中的promise对象,是实现异步的关键。

class Future(object):
def __init__(self):
self._callback = []
self._result = None
self._done = False def set_callback(self, cb):
self._callback.append(cb) def _run_callback(self):
for cb in self._callback:
cb() def set_result(self, result)
self._done = True
self._result = result
self._run_callback() def is_ready(self):
return self._done is True

_result:返回结果值

_done:是否完成

_callback:完成后,执行的回调列表

set_result():赋值result,Future对象完成,执行回调。

3.callback实现异步

from tornado.httpclient import AsyncHTTPClient
from tornado.web import RequestHandler class Test1Handler(RequestHandler):
def get(self, *args, **kwargs):
http_client = AsyncHTTPClient()
http_client.fetch('www.baidu.com', callback = self.on_fetched)
print('done') def on_fetched(self, response):
print('response')

运行结果:

源码分析:

def fetch(self, request, callback=None, raise_error=True, **kwargs):
if callback is not None:
def handle_future(future):
response = future.result()
self.io_loop.add_callback(callback, response)
future.add_done_callback(handle_future)
def handle_response(response):
if raise_error and response.error:
future.set_exception(response.error)
else:
future.set_result(response)
self.fetch_impl(request, handle_response)
return future def fetch_impl(self, request, callback):
raise NotImplementedError()

fetch函数返回一个Future类型对象,fetch_impl()执行完毕,返回结果response作为参数,执行回调handle_response

handle_response将response赋值给future。future状态变为已完成,执行future的callback函数handle_future,handle_future将callback加入ioloop执行队列,response作为参数。

由ioloop调度完成callback。

关键点在于,Future占位符控制了什么时候执行回调。

3.gen.coroutine实现异步

from tornado.httpclient import AsyncHTTPClient
from tornado.web import RequestHandler
from tornado import gen class Test1Handler(RequestHandler):
@gen.coroutine
def get(self, *args, **kwargs):
http_client = AsyncHTTPClient()
response = yield http_client.fetch('http://www.baidu.com')
print('response')

运行结果:

当执行到yield 表达式时,表达式会返回一个Future占位符,然后返回,当表达式执行完毕后,自动继续执行生成器。

关键点在于,gen.coroutine使生成器可以自动执行。

源码分析:

def coroutine(func, replace_callback=True):
return _make_coroutine_wrapper(func, replace_callback=True)
def _make_coroutine_wrapper(func, replace_callback):
try:
yielded = next(result)
except (StopIteration, Return) as e:
future.set_result(getattr(e, 'value', None))
except Exception:
future.set_exc_info(sys.exc_info())
else:
Runner(result, future, yielded)

result:生成器对象

yielded:Future对象,生成器首次执行结果,如果异常StopIteration,表示生成器执行完毕,将结果设置成future的值,返回,装饰器gen.coroutine返回的为Future对象。

Runner:判断yielded是否完成,完成则执行run函数,继续执行生成器;否则,添加run函数到这个Future对象yielded,执行完毕之后,才调用run函数。

class Runner(object):
def __init__(self, gen, result_future, first_yielded):
if self.handle_yield(first_yielded):
gen = result_future = first_yielded = None
self.run() def handle_yield(self, yielded):
self.future = convert_yielded(yielded) if not self.future.done() or self.future is moment:
self.io_loop.add_future(
self.future, lambda f: self.run())
return False
return True def run(self):
if self.running or self.finished:
return
try:
self.running = True
while True:
future = self.future
if not future.done(): #执行run时generator返回的那个future必须已经有结果,否则就没必要传回到generator中了
return
self.future = None
try:
value = future.result()
yielded = self.gen.send(value)
except (StopIteration, Return) as e:
#generator执行完毕并成功的处理
except Exception:
#generator执行过程中异常的处理
if not self.handle_yield(yielded):
return
finally:
self.running = False

handle_yield:判断Future对象yielded是否完成,未完成,注册run()函数回调到这个Future对象,完成,才调用。

run:将yielded这个Future对象的result,作为参数传递给生成器,继续执行生成器。

Tornado中gen.coroutine详解的更多相关文章

  1. Unity3D中的Coroutine详解

    Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...

  2. 【Unity3D/C#】Unity3D中的Coroutine详解

    Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...

  3. php中关于引用(&)详解

    php中关于引用(&)详解 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的变量名访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的 ...

  4. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  5. AngularJS select中ngOptions用法详解

    AngularJS select中ngOptions用法详解   一.用法 ngOption针对不同类型的数据源有不同的用法,主要体现在数组和对象上. 数组: label for value in a ...

  6. 【转载】C/C++中extern关键字详解

    1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...

  7. oracle中imp命令详解 .

    转自http://www.cnblogs.com/songdavid/articles/2435439.html oracle中imp命令详解 Oracle的导入实用程序(Import utility ...

  8. Android中Service(服务)详解

    http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...

  9. python中threading模块详解(一)

    python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...

随机推荐

  1. QTableView中使用Delegate方式来实现对特定列的文本进行换行

    问题:由于表格的一个列中,有个别文本过长,默认情况下,QTableView不支持对某列的文本换行,所以需要通过Delegate方式来实现这样的效果 头文件的Delegate #pragma once ...

  2. android软键盘弹出引起的各种不适终极解决方案

    android软键盘弹出引起的各种不适终极解决方案 以下描述如何解决ListView高度小于0时出现的UI问题. 创建RelativeLayout的子类TxrjRelativeLayout publi ...

  3. ios中MKHorizMenu用法

    下载地址 https://github.com/MugunthKumar/MKHorizMenuDemo直接 加入MKHorizMenu目录即可 下载包地址 http://pan.baidu.com/ ...

  4. iOS 性能调优

    1.内存空间的划分: 我们知道,一个进程占用的内存空间,包含5种不同的数据区:(1)BSS段:通常是存放未初始化的全局变量:(2)数据段:通常是存放已初始化的全局变量.(3)代码段:通常是存放程序执行 ...

  5. Linux内核的ioctl函数学习

    Linux内核的ioctl函数学习 来源:Linux公社  作者:Linux 我这里说的ioctl函数是在驱动程序里的,因为我不知道还有没有别的场合用到了ioctl, 所以就规定了我们讨论的范围.为什 ...

  6. apache kafka系列之Producer处理逻辑

     最近研究producer的负载均衡策略,,,,我在librdkafka里边用代码实现了partition 值的轮询方法,,,但是在现场验证时,他的负载均衡不起作用,,,所以来找找原因: 下文是一篇描 ...

  7. 重写Checkbox 改写选择框的大小

    /* 作者:Starts_2000 * 日期:2009-07-30 * 网站:http://www.csharpwin.com CS 程序员之窗. * 你可以免费使用或修改以下代码,但请保留版权信息. ...

  8. Docker(一):Docker入门教程

    如今Docker的使用已经非常普遍,特别在一线互联网公司.使用Docker技术可以帮助企业快速水平扩展服务,从而到达弹性部署业务的能力.在云服务概念兴起之后,Docker的使用场景和范围进一步发展,如 ...

  9. kubelet源码分析(version: git tag 1.7.6)

    一.概述 kubelet源码入口:cmd/kubelet/kubelet.go main() cmd/kubelet/app 包中的Run函数: 查看先参数,kubelet.KubeletDeps t ...

  10. 《JAVA与模式》之单例模式(转载)

    原文地址:http://blog.csdn.net/jason0539/article/details/23297037 概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿 ...