tornado 异步

tornado 异步总结的缘由

最近再看fluent python 中涉及到异步和非阻塞等,最近工作中使用的tornado 也在要使用 异步编程。两者看的云里雾里的。现在做一个梳理,理解其中的相关概念,并且应用到实战中。

tornado 异步

说明: 本程序的环境是Python3.6

先看下原生asyncio 中的几个概念,在tornado 中几乎是一样的。

  • event_loop 事件循环:程序开启一个无限循环,工程师会把一些函数注册到事件循环中。当满足事件发生的时候,调用相应的协程函数
  • coroutine 协程:协程对象,指一个async关键字定义的函数,它的调用不会立即执行函数,而是返回一个协程对象,协程对象需要注册到事件循环,由事件循环调用。
  • task 任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程的进一步封装,其中包含任务的各种状态。
  • future : 代表将来执行或者没有执行的任务的的结果。她和task上没有本质的区别。
  • anync/ await 这两个关键自是同时出现的:Python3.5 用于定义协程的关键字,async 定义一个协程,await定义一个协程,用于挂起阻塞的异步调用接口。


@gen.coroutine
tornado的 异步特性,必须使用异步的库(这句话如何李理解呢,一会有具体的实例来比较说明)。否则单个进程阻塞,根本不会达到异步效果,Tornado 异步库中最常用的异步库是asynHTTPClient .以及在其基础上实现的OpenID登录验证接口。另外更多的异步库可以在这里找到。包括用的比较多的MongoDB的Driver。

coroutine装饰器可以让本来靠回调的异步编程看起来像同步编程(一会会用代码区别理解)。其中便是利用Python生成器的send() 函数。在生成器中,yield关键字往往会与正常的return相比。它可以被当作迭代器,从而使用next()返回yield的结果。但是生成器还有另外一个用法,就是使用send方法,在生成器内部可以将yield的结果赋值给一个变量,而这个值就是通过外部生成器client来send的。理解上面这句话 首先要弄懂生成器的相关概念,在这里就不拓展生成器的概念了,网上和 flunt python等书都是最好的学习资料。

先看一个异步编程的实例

from tornado import gen
from tornado.platform.asyncio import to_asyncio_future,AsyncIOMainLoop
from tornado.httpclient import AsyncHTTPClient
import asyncio
import time

@gen.coroutine
def gen_test_new():
    return "okk"
@gen.coroutine
def aa():   
    yield gen.sleep(3)
    a = "ok"   
    a = yield gen_test_new()    
    return a

@gen.coroutine
def tornado_coroutine():    
    res1, res2 = yield [aa(),aa()]
    print(res1)
    print(res2)

AsyncIOMainLoop().install()
t1 = time.time()
asyncio.get_event_loop().run_until_complete(to_asyncio_future(tornado_coroutine()))
print(time.time() - t1)
 # 打印值
 okk
okk
3.002096652984619

上面分析可以看出本来执行两端代码如果是同步的话回事3秒的时间,但是使用了异步并发 只有差不多3秒,一般会多于3秒一点点。

从上面可以看出来每一个函数上面都注解了@gen.coroutine 装饰器,是为了让函数编程异步的,这就解释了上面说的tornado 必须使用异步的库。yield 后面是一个异步的函数,不然会报错,下面来看没有使用注解的运行结果。

from tornado import gen
from tornado.platform.asyncio import to_asyncio_future,AsyncIOMainLoop
from tornado.httpclient import AsyncHTTPClient
import asyncio
import time

# @gen.coroutine
def gen_test_new():
    return "okk"
@gen.coroutine
def aa():    
    yield gen.sleep(
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值