2014-01-09 96 views
23

在龙卷风中,我们平时写下面的代码来异步调用一个函数:Tornado的“收益率”与asyncio的“收益率”之间的区别?

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发货,可以从PIP安装的Python 3.3),我们使用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所取得的成果,以及这两种机制之间的区别。

回答

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对象;代码处理可以简单得多。事实上,Tornado Runner.run() method会执行显式类型检查来处理委派的任务。

+0

感谢您的快速回复。但我的问题与'产量'本身无关。我很担心Tornado和asyncio通过使用'yield'和'yield'来实现什么。 –

+0

@StarBrilliant:他们将任务推迟到稍后;发电机可以暂停,以便事件循环可以将控制传递给另一个发电机。 –

+0

@StarBrilliant:协程转轮将循环通过主动协程并给予每个执行机会。需要等待网络资源的协程可以立即立即产生,以允许控制传递给可能不需要等待的其他协程。 –