使用Tornado Python调用异步函数

时间:2017-05-23 16:04:04

标签: python python-2.7 asynchronous tornado

我正在尝试使用Tornado的gen.coroutine函数进行简单的异步调用。这是我目前的代码:

from tornado import gen
import tornado.ioloop
import tornado.web


class MainHandler(tornado.web.RequestHandler):

    @gen.coroutine
    def get(self):
        q = self.get_argument('query')
        print q
        response = yield self.process(q)
        self.write(response)

    @gen.coroutine
    def process(self, query):
        # just a long loop
        for i in range(int(query)*100):
            for j in range(i):
                a = 10*10*10*10*10*10
        return {'processed': True}


def make_app():
    return tornado.web.Application([
        (r"/search", MainHandler),
    ])

if __name__ == "__main__":
    app = make_app()
    port = 8888
    print "listening on port: ", port
    app.listen(port)
    tornado.ioloop.IOLoop.current().start()

但是,它不是以异步方式运行。我在这做错了什么?

2 个答案:

答案 0 :(得分:3)

您的"流程"方法只进行计算,所以它永远不会为Tornado的事件循环提供在其他任务上工作的机会,同时处理"在跑。 Tornado可以交错并发网络操作,但是它不能并行运行Python代码。并行化像你的"过程"方法需要多个Python子进程。

答案 1 :(得分:3)

您的函数阻止事件循环,在process()函数完成或将控制权重新放回事件循环之前,不能处理任何其他任务。对于这种情况,您可以简单地使用yield None(以前是yield gen.moment)来休息,让事件循环运行其他任务然后恢复处理。例如:

@gen.coroutine
def process(self, query):
    for i in range(int(query)*100):
        for j in range(i):
            a = 10*10*10*10*10*10
            if j % 500 == 0:
                yield None    # yield the inner loop

        if i % 500 == 0:
            yield None    # yield outer loop

    return {'processed': True}

希望这可以帮助您实现所需的并发级别。

参考

http://www.tornadoweb.org/en/stable/gen.html#tornado.gen.moment