龙卷风的“产量”和机制中的asyncio的“产量”之间的差异?

时间:2014-01-09 13:23:28

标签: python generator tornado yield

在Tornado中,我们通常编写以下代码来异步调用函数:

class MainHandler(tornado.web.RequestHandler):

    @tornado.gen.coroutine
    def post(self):
        ...
        yield self.handleRequest(foo)
        ...

    @tornado.gen.coroutine
    def handleRequest(self, foo):
        ...

但是在asyncio中(将在Python 3.4中附带,可以从Python 3.3的pip安装),我们使用yield from来实现同样的目的:

@asyncio.coroutine
def myPostHandler():
    ...
    yield from handleRequest(foo)
    ...


@asyncio.coroutine
def handleRequest(foo)
    ...

从代码中看,差异为yieldyield from。但是,前handleRequest(foo)返回tornado.concurrent.Future个对象,后者返回generator个对象。

我的问题是,机制中的两件事有什么区别?控制流程如何?谁调用实际的handleRequest并检索其返回值?

附加:我具有Python生成器和迭代器的基本知识。我想通过使用这些来了解Tornado和asyncio的成就,以及这两种机制之间的区别。

1 个答案:

答案 0 :(得分:22)

两者之间存在巨大差异。 yield from需要另一台发电机并继续从该发电机中产生(委托责任,因为它)。 yield只会产生一个值。

换句话说,yield from,在最简单的情况下,可以替换为:

for value in self.handleRequest(foo):
    yield value

如果用yield from <expression>替换yield <expression>行,则将整个生成器返回给调用者,而不是生成器生成的值。

yield from语法仅在Python 3.3中引入,请参阅PEP 380: Syntax for Delegating to a Subgenerator。除了Python 3.3之外,Tornado还支持Python版本2.6,2.7和3.2,因此它不能依赖于yield from语法。另一方面,asyncio是3.4中添加的核心Python库,完全可以依赖于yield from生成器委派语法。

因此,Tornado必须对@tornado.gen.coroutine生成器产生的值进行后处理,以检测是否产生了tornado.concurrent.Future个对象; @asyncio.coroutine代码处理可以更简单。事实上,Tornado Runner.run() method会进行显式类型检查以处理委派任务。