2015-04-17 60 views
3

今天,我想讓一些同步Python庫異步工作,但它不起作用。經過一系列測試後,我發現即使是yield tornado.gen.sleep(N)也同步工作。爲什麼龍捲風異步不起作用

這裏是我的代碼:

import time 
import tornado.web 
import tornado.gen 
import tornado.ioloop 
import os 


class MainHandler(tornado.web.RequestHandler): 
    def get(self): 
     self.render("test.htm") 


class SleepHandler(tornado.web.RequestHandler): 
    def get(self): 
     time.sleep(2) 
     self.write("Good morning!") 


class YSleepHandler(tornado.web.RequestHandler): 
    @tornado.gen.coroutine 
    def get(self): 
     yield tornado.gen.sleep(2) 
     self.write("Good morning!") 


def main(): 
    app = tornado.web.Application([ 
     (r"/sleep", SleepHandler), 
     (r"/ysleep", YSleepHandler), 
     (r"/", MainHandler), 
     ], debug=True, template_path=os.path.split(
      os.path.realpath(__file__))[0]) 
    app.listen(8888) 
    try: 
     tornado.ioloop.IOLoop.current().start() 
    except: 
     tornado.ioloop.IOLoop.current().stop() 


if __name__ == "__main__": 
    main() 

我用下面的代碼來測試異步函數工作或沒有(在TEST.HTM - 爲MainHandler模​​板文件):

for(var i = 0; i < 10; i++){ 
       $.get("/sleep"); 
      } 
for(var i = 0; i < 10; i++){ 
       $.get("/ysleep"); 
      } 

但最後,我得到了一個意想不到的result

怎麼回事?我在Python2.7和Python3.4環境下都嘗試過。

回答

1

最後,通過在URL的末尾添加一些獨特的無用參數來重新解決此問題。

for(var i = 0; i < 10; i++){ 
       $.get("/sleep"); 
      } 
for(var i = 0; i < 10; i++){ 
       $.get("/ysleep"); 
      } 

如果你使用上面的代碼測試出來的結果,你喜歡你正在使用的同步代碼將得到相同的結果(因爲龍捲風將返回304不修改,這是一個同步功能)。但是如果使用下面的代碼,則同步和異步之間的差異將被完全說明。

for(var i = 0; i < 10; i++){ 
       $.get("/sleep", {"random": Math.random()}); 
      } 
for(var i = 0; i < 10; i++){ 
       $.get("/ysleep", {"random": Math.random()}); 
      } 
+1

這是一些瀏覽器的限制,他們不會打開多個連接到同一個URL。因此,在第一個代碼示例中,瀏覽器實際上正在執行阻止。 –

+0

是的,@AntBlackshaw是對的。看到[這個類似的問題](http://stackoverflow.com/questions/24106503/python-tornado-asynchronous-request-is-blocking) – dano

0

你會看到這種行爲,因爲在協同程序中產生有效地將控制轉移回Tornado的IOLoop。這並不意味着它將結果返回給客戶端 - 僅僅是它將控制權返回給Tornado,以便IOLoop不會被長時間運行的請求阻止。

這對你的代碼的影響是Tornado會在SleepHandler運行時阻塞,而當YSleepHandler運行時它不會阻塞。在這兩種情況下,只有當您的處理程序調用self.write()時,響應纔會返回給客戶端,但在YSleepHandler的情況下,可以在處理程序正在運行時處理其他請求,因爲IOLoop未被阻止。

+0

事實上,我單獨測試了兩個處理程序的結果,SleepHandler在我測試YSleepHandler時未被調用。但是,最後我得到了[結果](http://i.stack.imgur.com/s0f2A.jpg)。你能告訴我如何以正確的方式重寫這段代碼嗎? –