Tornado @tornado.gen.coroutine 与 yield
在使用 Tornado 的过程中产生了以下疑问:
- 什么时候需要给函数增加
@tornado.gen.coroutine
- 什么时候调用函数需要
yield
@tornado.gen.coroutine
与 yield
是如何工作的
包含 yield
的函数是一个 generator[1]。@gen.coroutine
通过 yield
与 generator 沟通、通过返回 Future
与协程的调用者沟通。
具体沟通情况:
@gen.coroutine
收到从 generator 返回的Future
- "unwraps"
Future
获得结果 - 将结果发送回 generator 以作为
yield
表达式的结果
如何调用协程
上文提到,
@gen.coroutine
通过返回Future
与协程的调用者沟通
所以我们必须 "unwraps" 这个 Future
才能得到结果。
所以在绝大部分情况下,任何调用协程的函数本身必须是一个协程,并且在调用中要使用 yield
。
@gen.coroutine
def good_call():
# yield will unwrap the Future returned by divide() and raise
# the exception.
yield divide(1, 0)
注意,yield
只有在 @gen.coroutine
中才会 "unwraps" 一个 Future
,如果没有 @gen.coroutine
,那么 yield
只会将该函数变为一个而普通的生成器,比如下面两个例子。
- 错误的
import tornado.gen
from tornado.ioloop import IOLoop
from tornado.gen import Return
@tornado.gen.coroutine
def call_me():
raise Return('result')
def f():
r = yield call_me()
print(r) # tornado.gen.BadYieldError: yielded unknown object <generator object f at 0x104a34320>
IOLoop.current().run_sync(f)
错误的原因是:run_sync
会调用 f()
,然后尝试将 f()
的结果转换为 Future
,转换的函数如下:
# env/lib/python2.7/site-packages/tornado/gen.py:1259
def convert_yielded(yielded):
"""Convert a yielded object into a `.Future`.
The default implementation accepts lists, dictionaries, and Futures.
If the `~functools.singledispatch` library is available, this function
may be extended to support additional types. For example::
@convert_yielded.register(asyncio.Future)
def _(asyncio_future):
return tornado.platform.asyncio.to_tornado_future(asyncio_future)
.. versionadded:: 4.1
"""
# Lists and dicts containing YieldPoints were handled earlier.
if yielded is None:
return moment
elif isinstance(yielded, (list, dict)):
return multi(yielded)
elif is_future(yielded):
return yielded
elif isawaitable(yielded):
return _wrap_awaitable(yielded)
else:
raise BadYieldError("yielded unknown object %r" % (yielded,))
由于 f()
返回的是一个 generator
对象,不符合转换的要求,所以报错。如果给 f()
加上 @tornado.gen.coroutine
,那么装饰器会将 f()
返回的结果转换为 Future
,符合 elif is_future(yielded):
,也就能顺利运行。
- 正确的
import tornado.gen
from tornado.ioloop import IOLoop
from tornado.gen import Return
@tornado.gen.coroutine
def call_me():
raise Return('result')
@tornado.gen.coroutine
def f():
r = yield call_me()
print(r) # result
IOLoop.current().run_sync(f)
总结
- 当调用一个协程时,
@tornado.gen.coroutine
与yield
必须同时出现调用函数中 - 如果只是在协程中执行操作或者直接返回结果,有
@tornado.gen.coroutine
和 return(raise Return)就够了
参考
- https://docs.python.org/2.4/ref/yield.html
- http://www.tornadoweb.org/en/stable/guide/coroutines.html#how-it-works
Tornado @tornado.gen.coroutine 与 yield的更多相关文章
- 使用tornado的gen.coroutine进行异步编程
在tornado3发布之后,强化了coroutine的概念,在异步编程中,替代了原来的gen.engine, 变成现在的gen.coroutine.这个装饰器本来就是为了简化在tornado中的异步编 ...
- Tornado中gen.coroutine详解
1.gen.coroutine的作用 自动执行生成器 2.Future对象 在介绍异步使用之前,先了解一下Future对象的作用. Future简单可以理解为一个占位符,将来会执行的对象,类似java ...
- Tornado源码分析系列之一: 化异步为'同步'的Future和gen.coroutine
转自:http://blog.nathon.wang/2015/06/24/tornado-source-insight-01-gen/ 用Tornado也有一段时间,Tornado的文档还是比较匮乏 ...
- 如何捕捉@tornado.gen.coroutine里的异常
from tornado import gen from tornado.ioloop import IOLoop @gen.coroutine def throw(a,b): try: a/b ra ...
- 使用tornado的gen模块改善程序性能
之前在公司的一个模块,需要从另一处url取得数据,我使用了Python的一个很著名的lib,叫做requests.但是这样做极大的降低了程序的性能,因为tornado是单线程的,它使用了所谓的reac ...
- yield与gen.coroutine
def d(): for i in range(2): yield i def b(): yield d() print("b") yield "bb" def ...
- 【Unity】协程Coroutine及Yield常见用法
最近学习协程Coroutine,参考了别人的文章和视频教程,感觉协程用法还是相当灵活巧妙的,在此简单总结,方便自己以后回顾.Yield关键字的语意可以理解为“暂停”. 首先是yield return的 ...
- tornado异步请求的理解(转)
tornado异步请求的理解 http://www.kankanews.com/ICkengine/archives/88953.shtml 官网第一段话: Tornado is a Python w ...
- PythonWEB框架之Tornado
前言 Tornado(龙卷风)和Django一样是Python中比较主流的web框架,Tornado 和现在的主流 Web 服务器框架也有着明显的区别:Tornado自带socket,并且实现了异步非 ...
随机推荐
- libvirt网络过滤规则简单总结
libvirt网络过滤规则, 一个过滤规则定义的示例: < filter name='no-ip-spoold'chain='ipv4' > < uuid >fce8ae33 ...
- android.animation(5) - PropertyValuesHolder与Keyframe(转)
前几篇给大家讲了ValueAnimator.ObjectAnimator的知识,讲解了它们ofInt(),ofFloat(),ofObject()函数的用法.细心的同学可能会注意到,ValueAnim ...
- 每日英语:Stalled Project Shows Why China's Economy Is Wobbling
CAOFEIDIAN, China $91 billion industrial project here, mired in debt and unfulfilled promise, sugge ...
- 认识rem
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- HDFS设计思路,HDFS使用,查看集群状态,HDFS,HDFS上传文件,HDFS下载文件,yarn web管理界面信息查看,运行一个mapreduce程序,mapreduce的demo
26 集群使用初步 HDFS的设计思路 l 设计思想 分而治之:将大文件.大批量文件,分布式存放在大量服务器上,以便于采取分而治之的方式对海量数据进行运算分析: l 在大数据系统中作用: 为各类分布式 ...
- Python异常处理try...except...finally raise assert
异常处理:try ...except try代码块放置容易发生异常的语句:except代码块放置处理异常的语句try ...except...finally finally代码快是任何时候都会执行的 ...
- java 远程调试 remote java application
1.在本地eclipse中,打开debug configuration,在弹出的窗口中,点击左边的remote java application. 2.在右边的窗口中,输入项目名称.远程主机的地址和端 ...
- Bootstrap学习笔记(7)--轮播
说明: 1. 幻灯片效果,外面的div有个id="myppt",class="carousel slide"这个是有图片滑动效果,不加就是直接瞬间换图片,dat ...
- 混合模式程序集是针对“v2.0.50727”版的运行时生成的
混合模式程序集是针对“v2.0.50727”版的运行时生成的,在没有配置其他信息的情况下,无法在 4.0 运行时中加载该程序集. 由于“system.data.sqlite.dll”不完整造成的. 在 ...
- 对map进行排序
public class TreeMapTest { public static void main(String[] args) { Map<String, String& ...