2014-01-09 41 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:協程轉輪將循環通過主動協程並給予每個執行機會。需要等待網絡資源的協程可以立即立即產生,以允許控制傳遞給可能不需要等待的其他協程。 –