10

基于 Python 生成器的 Tornado 协程异步

 3 years ago
source link: https://www.linuxzen.com/ji-yu-python-sheng-cheng-qi-de-tornado-xie-cheng-yi-bu.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Home Menu

基于 Python 生成器的 Tornado 协程异步

Gray King | Fri 19 December 2014

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, print_function, division, 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 的协程异步并不是这三言两语能说清楚的, 其中有很复杂的封装和传递, 有兴趣可以自己 阅读源码.


Recommend

  • 87

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

  • 9
    • justpic.org 3 years ago
    • Cache

    tornado异步网络编程实践

    tornado异步网络编程实践  2016-09-08  约 834 字   预计阅读 2 分钟    次阅读   ...

  • 11

    先说一些废话 PHP 5.5 以来,新的诸多特性又一次令 PHP 焕发新的光彩,虽然在本文写的时候已是 PHP 7 alpha 2 发布后的一段时间,但此时国内依旧是 php 5.3 的天下。不过我认为新的特性迟早会因为旧的版本的逐渐消失而变得越发重要,尤其是 PHP 7 的正...

  • 12

    渡劫 C++ 协程(2):实现一个序列生成器 发表于 2022-03-11 阅读次数: 4 本文字数: 8.8k 阅读时长 ≈ 16 分钟序列生成器是一个非常经典的协程应用场景。现在我们已经了解了绝大部分 C++ 协程的特性,...

  • 5

    渡劫 C++ 协程(3):序列生成器的泛化和函数式变换 发表于 2022-03-14 阅读次数: 2 本文字数: 7.8k 阅读时长 ≈ 14 分钟我们还可以对序列生成器产生的数据流做进一步的筛选和处理,而这一切都可以基于协程去实现。

  • 10
    • www.linuxzen.com 3 years ago
    • Cache

    使用Tornado进行网络异步编程

    Tornado Tornado 是一款非阻塞可扩展的使用Python编写的web服务器和Python Web框架, 可以使用Tornado编写Web程序并不依赖任何web服务器直接提供高效的web服务.所以Tornado不仅仅是一个web框架而且还是一款可以...

  • 9

    很古老的用法了,现在大多用的aiohttp库实现,这篇记录仅仅用做个人的协程底层实现的学习。 争取用看得懂的字来描述问题。 1.什么是yield 如果还没有怎么用过的话,直接把yield看做成一种特殊的return(PS:本质 generator(...

  • 10

    tornado原理介绍及异步非阻塞实现方式 以下内容根据自己实操和理解进行的整理,欢迎交流~ 在tornado的开发中,我们一般会见到以下四个组成部分。 ioloop: 同一个ioloop实例运...

  • 6

    Python3的原生协程(Async/Await)和Tornado异步非阻塞首页 - Python/2019-09-20

  • 6

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK