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_statementdef 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_statementfrom tornado import genfrom tornado import webfrom tornado import httpclIEntclass 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框架中的协程异步实现原理所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)