Tornado中gen.coroutine详解
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详解的更多相关文章
- Unity3D中的Coroutine详解
Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...
- 【Unity3D/C#】Unity3D中的Coroutine详解
Unity中的coroutine是通过yield expression;来实现的.官方脚本中到处会看到这样的代码. 疑问: yield是什么? Coroutine是什么? unity的coroutin ...
- php中关于引用(&)详解
php中关于引用(&)详解 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的变量名访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的 ...
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...
- AngularJS select中ngOptions用法详解
AngularJS select中ngOptions用法详解 一.用法 ngOption针对不同类型的数据源有不同的用法,主要体现在数组和对象上. 数组: label for value in a ...
- 【转载】C/C++中extern关键字详解
1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...
- oracle中imp命令详解 .
转自http://www.cnblogs.com/songdavid/articles/2435439.html oracle中imp命令详解 Oracle的导入实用程序(Import utility ...
- Android中Service(服务)详解
http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...
- python中threading模块详解(一)
python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...
随机推荐
- 转:3d max 2013 安装教程,凭着一种互联网精神提供给广大朋友
看到有人在ps区咨询如何安装3d max教程,当你进行第一步之前,请先断开网络连接第一步:运行安装程序 第二步:接受安装协议,点击下一步会提示输入序列号 第三步:你会看到已经安装完成了的界面 第四部: ...
- Dockerfile 构建google-chrom应用
cat Dockerfile.chrome FROM centos MAINTAINER zh******ech.cn ENV LANG en_US.UTF-8 RUN /bin/cp /usr/sh ...
- ios中 radioButton和DataPIcker,九宫格封装好使用
下载地址 http://pan.baidu.com/share/link?shareid=2894506499&uk=923776187 引用这几个文件 radiobutton.封装好单选按钮 ...
- Solr删除managedschema
一.创建solr核心 solr createcore 二.删除managedschema managedschema是solr自动生成的,里面包含大量无用配置. solr是检查用户定义的schema. ...
- Linux下Setuid命令! 转载
Linux下Setuid命令! 转载 在Linux系统中每个普通用户都可以更改自己的密码,这是合理的设置. 问题是:用户的信息保存在文件/etc/passwd中,用户的密码保存在文件/etc/sha ...
- linux 版本中 i386/i686/x86-64/pcc 等的区别
在查看dpdk官方文档的时候,发现有 这样(kernel - devel.x86_64; kernel - devel.ppc64:glibc.i686)这样的安装包信息,收集了点资料来分析这三者的关 ...
- vim自动缩进设置
需要软件 vim 下载地址 http://www.vim.org code_complete.vim 插件 http://www.vim.org/scripts/script.php?script ...
- PHP通过soap调用c#的WebService
1:C# Contact public class Contact { private int _Id; private string _Name; public int id { get { ret ...
- 安卓 AsyncHttpClient - “Content-Type not allowed!”
使用 http://loopj.com/android-async-http/ 的异步网络请求工具使用BinaryHttpResponseHandler来完成文件下载时总是报错,“org.apache ...
- golang ----rune数据类型
查询,官方的解释如下: // rune is an alias for int32 and is equivalent to int32 in all ways. It is // used, by ...