在使用 Tornado 的过程中产生了以下疑问:

  • 什么时候需要给函数增加 @tornado.gen.coroutine
  • 什么时候调用函数需要 yield

@tornado.gen.coroutineyield 是如何工作的

包含 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 functionmay 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 momentelif isinstance(yielded, (list, dict)):return multi(yielded)elif is_future(yielded):return yieldedelif 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)  # resultIOLoop.current().run_sync(f)

总结

  • 当调用一个协程时,@tornado.gen.coroutineyield 必须同时出现调用函数中
  • 如果只是在协程中执行操作或者直接返回结果,有 @tornado.gen.coroutine 和 return(raise Return)就够了

参考

  1. https://docs.python.org/2.4/ref/yield.html
  2. http://www.tornadoweb.org/en/stable/guide/coroutines.html#how-it-works

转载于:https://www.cnblogs.com/jay54520/p/9118621.html

Tornado @tornado.gen.coroutine 与 yield相关推荐

  1. tornado源码分析(四)之future、gen.coroutine

    future是什么 在事件驱动编程模型中,会有很多的事件循环,各事件循环在创建异步事件时可以同时创建一个future对象,并将创建的异步事件与该future对象存储在一起,并将所有传入的callbac ...

  2. tornado协程(coroutine)原理

    tornado中的协程是如何工作的 本文将按以下结构进行组织,说明tornado中协程的执行原理 协程定义 生成器和yield语义 Future对象 ioloop对象 函数装饰器coroutine 总 ...

  3. tornado协程(coroutine)

    tornado中的协程是如何工作的 本文将按以下结构进行组织,说明tornado中协程的执行原理 协程定义 生成器和yield语义 Future对象 ioloop对象 函数装饰器coroutine 总 ...

  4. 简单总结协程Coroutine及Yield常见用法

    原文地址:http://blog.csdn.net/qq_18995513/article/details/51944602 最近学习协程Coroutine,参考了别人的文章和视频教程,感觉协程用法还 ...

  5. ajax长轮询tornado,Tornado长轮询和WebSocket

    Http协议是一种请求响应式协议, 不允许服务端主动向客户端发送信息. 短轮询是一种简单的实现服务端推送消息的解决方案, 客户端以一定间隔自动向服务端发送刷新请求, 服务端返回要推送的消息作为响应. ...

  6. 实践,用tornado实现自定义协议server

    前言 俗话说"光说不练假把式",上一篇文里都只是光看着别人的源码说,貌似有点纸上谈兵的意思. 所以这次写一个简单的,自己定义协议的server. 既可以熟悉Future和corou ...

  7. Python Web框架Tornado的异步处理代码演示样例

    1. What is Tornado Tornado是一个轻量级但高性能的Python web框架,与还有一个流行的Python web框架Django相比.tornado不提供操作数据库的ORM接口 ...

  8. 自学Python第二十六天- Tornado 框架

    自学Python第二十六天- Tornado 框架 安装及基础引用 创建.配置.初始化应用及简单运行服务 创建应用 对 app 进行设置 另一种设置方法 一些其他的配置 关于调试模式 设置路由处理器 ...

  9. 关于Tornado实现多进程/多线程的理解及参考

    方案所用到模块及模块介绍: import tornado.gen tornado.gen 模块是一个基于 python generator 实现的异步编程接口. 通过该模块提供的 coroutine ...

  10. Tornado 异步协程coroutine原理

    协程定义: 协程,又称微线程,纤程.英文名Coroutine. 子程序,或者称为函数,在所有语言中都是层级调用,比如A调用B,B在执行过程中又调用了C,C执行完毕返回,B执行完毕返回,最后是A执行完毕 ...

最新文章

  1. 机器学习之数学基础(一)~maximum likelihood
  2. Java程序员面试中的多线程问题
  3. 复习日记-validate表单校验插件/菜单管理dTree
  4. Golang的值类型和引用类型的范围、存储区域、区别
  5. JBoss 4.2.x Spring 3 JPA Hibernate教程第2部分
  6. 电脑有回声_电脑连接麦克风有回音怎么办?麦克风回声的解决方法
  7. AcWing 180. 排书
  8. Linux 账户信息显示和实现账户安全
  9. 正则,bs4 ,xpath 和jsonpath 的匹配规则
  10. NP、OSPF 缺省路由
  11. HTML+CSS网页设计视频教程
  12. WebApi实现验证授权Token,WebApi生成文档等(转)
  13. elasticsearch APM功能全解 一
  14. 作为一个渗透测试学习者必知必读的好书推荐
  15. linux ipcs 命令详解
  16. Netlogon漏洞复现
  17. template 的 用法
  18. 华为ensp的缺省_利用华为ENSP模拟器分析和配置中小型企业网络的综合实验
  19. 指定SpringBoot内嵌Tomcat的版本,修复(CVE-2021-42340)漏洞
  20. 对于windows10家庭版无法勾选Hyper-V的问题的解决

热门文章

  1. 微信小助手WeChatExtension中文版安装教程
  2. 13.5 Prepared Statements
  3. 【青少年编程竞赛须知】青少儿学习编程能够参加哪些比赛?
  4. 爬虫剑谱第七页(输入关键词爬取拼多多商品信息并进行保存)
  5. Android Zxing 相册二维码/条码图片识别
  6. 数据库系统原理与应用教程(081)—— MySQL 视图(View)的创建与使用
  7. 有奖互动 | 感恩节福利放送中
  8. python股票代码示例_Python应用实例之股市数据分析
  9. java定义个字符串_Java定义字符串(2种方式)
  10. EasyUI 日历实现日程提醒