Tornado 协程

Posted Erick - LONG

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tornado 协程相关的知识,希望对你有一定的参考价值。

同步异步I/O客户端

from tornado.httpclient import HTTPClient,AsyncHTTPClient

def ssync_visit():
    http_client = HTTPClient()
    response = http_client.fetch(www.baidu.com) # 阻塞,直到网站请求完成
    print(response.body)

def hendle_response(response):
    print(response.body)
def async_visit():
    http_client = AsyncHTTPClient()
    http_client.fetch(www.baidu.com,callback=hendle_response) # 非阻塞

async_visit()

协程

1、编写协程函数

from tornado import gen # 引入协程库

from tornado.httpclient import AsyncHTTPClient

@gen.coroutine
def coroutine_visit():
    http_client = AsyncHTTPClient()
    response = yield http_client.fetch(www.baidu.com)
    print(response.body)

2、调用协程函数

由于Tornado协程基于python的yield关键字实现,所以不能调用普通函数一样调用协程函数

协程函数可通过以下三种方式调用

  • 在本身是协程的函数内通过yield关键字调用
  • 在IOLoop尚未启动时,通过IOLoop的run_sync()函数调用
  • 在IOLoop已经启动时,通过IOLoop的spawn_callback()函数调用

  下面是一个通过协程函数调用协程函数的例子

@gen.coroutine
def outer_coroutine():
    print(开始调用另一个协程)
    yield coroutine_visit()
    print(outer_coroutine 调用结束)
outer_coroutine和coroutine_visit都是协程函数,他们之间可以通过yield关键字进行调用

IOLoop 是Tornado的主事件循环对象,Tornado程序通过它监听外部客户端的访问请求,并执行相应的操作,当程序尚未进入IOLoop的runing状态时,可以通过run_sync()函数调用协程函数,比如:
from tornado import gen # 引入协程库
from tornado.ioloop import IOLoop
from tornado.httpclient import AsyncHTTPClient

@gen.coroutine
def coroutine_visit():
    http_client = AsyncHTTPClient()
    response = yield http_client.fetch(http://www.baidu.com)
    print(response.body)

def func_normal():
    print(开始调用协程)
    IOLoop.current().run_sync(lambda: coroutine_visit())
    print(结束协程调用)
func_normal()

本例中run_sync()函数将当前函数的执行进行阻塞,直到被调用的协程执行完成

Tornado 要求协程函数在IOloop的running状态才能被调用,只不过run_sync函数自动完成了启动,停止IOLoop的步骤,他的实现逻辑为:启动IOLoop-调用被lambda封装的协程函数-停止IOLoop

当tornado程序已经处于running 状态时协程的调用如下:

def func_normal():
    print(开始调用协程)
    IOLoop.current().spawn_callback(coroutine_visit)
    print(结束协程调用)
func_normal()
开始调用协程
结束协程调用

本例中spawn_callback函数不会等待被调用的协程执行完成,而协程函数将会由IOLoop在合适的时机进行调用,并且spawn_callback函数没有提供电泳返回值的方法,所以hi能用该函数调用没有返回值的协程函数

3、在协程中调用阻塞函数

在协程中直接调用阻塞函数会影响协程本身的性能,所以tornado提供了在协程中利用线程池调度阻塞函数,从而不影响协程本身继续执行的方法,实例代码如下:

from concurrent.futures import ThreadPoolExecutor
from tornado import gen
thread_pool = ThreadPoolExecutor(2)

def mySleep(count):
    import time
    for i in range(count):
        time.sleep(1)

@gen.coroutine
def call_backing():
    print(开始调用当前函数)
    yield thread_pool.submit(mySleep,10)
    print(结束调用)

call_backing()

4、在协程中的等待多个异步调用

tornado允许在协程中用一个yield关键字等待多个异步调用,只需把这些调用用列表或字典的方式传递给yield关键字即可

实例如下:

from tornado import gen # 引入协程库
from tornado.ioloop import IOLoop
from tornado.httpclient import AsyncHTTPClient

@gen.coroutine
def coroutine_visit():
    http_client = AsyncHTTPClient()
    list_response = yield [http_client.fetch(http://www.baidu.com),
                           http_client.fetch(http://www.sina.com),
                           http_client.fetch(http://www.163.com)
                           ]
    for response in list_response:
        print(response.body)

def func_normal():
    print(开始调用协程)
    IOLoop.current().run_sync(lambda: coroutine_visit())
    print(结束协程调用)
func_normal()

字典同理,不再演示

Tornado 网站

异步化,协程化

 

以上是关于Tornado 协程的主要内容,如果未能解决你的问题,请参考以下文章

tornado异步原理

深入tornado中的协程

深入tornado中的协程

tornado 协程

tornado中的协程是如何工作的

Tornado 协程