python - Tornado的 "yield"和asyncio的 "yield from"在机制上的区别?

标签 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 通过使用这些实现了什么,以及这两种机制之间有什么区别。

最佳答案

两者之间存在巨大差异。 yield from获取另一个生成器并继续从该生成器产生(委托(delegate)责任,就像它一样)。 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生成器委托(delegate)语法可用。

因此,Tornado 将不得不对 @tornado.gen.coroutine 产生的值进行后处理。生成器来检测 tornado.concurrent.Future对象已产生; @asyncio.coroutine代码处理可以简单得多。确实是Tornado Runner.run() method执行显式类型检查以处理委派任务。

关于python - Tornado的 "yield"和asyncio的 "yield from"在机制上的区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21021498/

相关文章:

python - 使用python将视频(任何类型)转换为音频-mp3格式-

python - 创建一个修改了一个元素的新元组

python - Tornado Sentry 集成

python - 被tornado.concurrent.Future异常困惑

python - 如何在从 Tornado 流式传输视频时减少阻塞

python - 比较单列的行元素。如果有 2 个连续的 L,则从 High 列中选择最低的,忽略其他。相反,如果 2 L

java - 通过套接字将 String 和 Byte[] 从 Android 应用程序发送到 Python 服务器

Python 跨数据帧匹配项目

python - 如何在不耗尽python内存的情况下遍历大文件?

python - 向 xrange() 添加任意元素?