您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

简单介绍Python的Tornado框架中的协程异步实现原理

5b51 2022/1/14 8:17:54 python 字数 8174 阅读 361 来源 www.jb51.cc/python

Tornado4.0已经发布了很长一段时间了,新版本广泛的应用了协程(Future)特性.我们目前已经将Tornado升级到最新版本,而且也大量的使用协程特性.

概述

Tornado 4.0 已经发布了很长一段时间了,新版本广泛的应用了协程(Future)特性. 我们目前已经将 Tornado 升级到最新版本,而且也大量的使用协程特性.

很长时间没有更新博客,今天就简单介绍下 Tornado 协程实现原理,Tornado 的协程是基于 Python 的生成器实现的,所以首先来回顾下生成器.
生成

Python 的生成器可以保存执行状态 并在下次调用的时候恢复,通过在函数体内使用 yield 关键字 来创建一个生成器,通过内置函数 next 或生成器的 next 方法来恢复生成器的状态.

def test():
  yield 1

我们调用 test 函数,此时并不会返回结果,而是会返回一个生成

>>> test()
<generator object test at 0x100b3b320>

我们调用其 next 方法则返回 yield 关键字之后的内容.

>>> t = test()
>>> t.next()
1

如果我们接着调用 next 方法,后面又没有 yield 关键字继续返回的话,会抛出一个 StopIteration 异常.

yield 关键字不仅仅能从生成器内部返回状态,同时也可以将外部信息传递到生成器内部,通过将 yeild 关键里赋值给变量,并调用生成器的 send 方法来将对象传递到生成器 内部. 需要注意的是生成器的开始必须调用其 next 方法,后面 send 方法调用的同时 也会触发 next 动作. 如果没有变量接收 yield 关键字那么 send 传递的值将会 被丢弃.

>>> def test():
  a = yield
  print(a)

首先调用 next 上面函数返回的生成器将返回 None,如果这时候直接调用 next 将 会给生成器发送 None,如果调用 send 发送一个值,将打印这个值并抛出 StopIteration 异常.
一个简单地协程

以上就是实现协程的所有基础,为了加深理解,我们这里写一个小例子,例子我们只使用协程 开启两个甚至多个死循环,下面就是一个极其简单地例子::

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from __future__ import absolute_import,print_function,division,with_statement

def loop1():
  """ 循环1负责抛出一个函数和对应的参数,并接收结果
  """
  a = 0
  ret = 1
  while True:
    ret = yield sum,[a,ret]
    a,ret = ret,a
    print("Loop1 ret",ret)

def loop2():
  """ 循环2 负责接收函数并计算结果,然后 yield 出结果
  """
  while True:
    func,args = yield
    yield func(args)
    print("Loop2")


l1 = loop1()
l2 = loop2()
tmp = l1.next()

for i in range(10):
  l2.next()
  ret = l2.send(tmp)
  tmp = l1.send(ret)


上面例子里 loop1 负责产生任务,loop2 负责执行任务,主循环负责调度任务并将任务结果发回给 任务产生者.
Tornado 如何做的

我们首先看一个使用 Tornado 协程异步的例子

#!/usr/bin/env python
# -*- coding:utf-8 -*-

from __future__ import absolute_import,with_statement

from tornado import gen
from tornado import web
from tornado import httpclient


class ActionHandler(web.RequestHandler):

  @gen.coroutine
  def get(self):
    response = yield httpclient.AsyncHTTPClient().fetch("http://www.linuxzen.com")

    # ...

其实原理在上面简单地例子里已经讲清楚了,我们来简单分析一遍上面的例子,首先 Tornado 得到 ActionHandler.get 方法抛出(next)的一个任务,然后异步的去执行任务,当任务(网络请求)结束或 异常时 Tornado 取得事件通知然后将结果放回(send)到该方法中让该方法继续执行.

由于是异步的,调用这个方法并不会阻塞其他任务执行.

这时候我们的方法其实就是上个例子 loop1 函数,而 Tornado 调度并执行了其抛出的任务.
总结

Tornado 的协程异步可以让异步看起来是顺序执行的,可以从一大串的 callback 中解脱出来.

Tornado 的协程异步并不是这三言两语能说清楚的,其中有很复杂的封装和传递,有兴趣可以自己 阅读源码.

总结

以上是编程之家为你收集整理的简单介绍Python的Tornado框架中的协程异步实现原理全部内容,希望文章能够帮你解决简单介绍Python的Tornado框架中的协程异步实现原理所遇到的程序开发问题。


如果您也喜欢它,动动您的小指点个赞吧

除非注明,文章均由 laddyq.com 整理发布,欢迎转载。

转载请注明:
链接:http://laddyq.com
来源:laddyq.com
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


联系我
置顶