2015-04-17 41 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)。你能告诉我如何以正确的方式重写这段代码吗? –