简体   繁体   English

用Tornado Python进行异步函数调用

[英]Async function call with Tornado Python

I'm trying to make a simple async call, using gen.coroutine function of Tornado. 我正在尝试使用Tornado的gen.coroutine函数进行简单的异步调用。 This is my current code: 这是我当前的代码:

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()

However, it is not behaving in an async manner. 但是,它不是以异步方式运行。 What am I doing wrong in this? 我在这方面做错了什么?

Your "process" method does only calculation, so it never provides Tornado's event loop an opportunity to work on other tasks while "process" is running. 您的“过程”方法仅进行计算,因此,在“过程”运行时,它永远不会为Tornado的事件循环提供执行其他任务的机会。 Tornado can interleave concurrent network operations, however, it cannot run Python code in parallel. 龙卷风可以交错并发网络操作,但是,它不能并行运行Python代码。 To parallelize a function like your "process" method requires multiple Python subprocesses. 要并行化“过程”方法之类的函数,需要多个Python子过程。

Your function is blocking the event loop and no other tasks can be handled until either the process() function completes or it relinquishes control back to the event loop. 您的函数正在阻塞事件循环,直到process()函数完成或将控制权交还给事件循环之前,其他任何任务都无法处理。 For situations like this, you can use simply yield None (it used to be yield gen.moment ) to take a break and let the event loop run other tasks then resume processing. 在这种情况下,您可以简单地使用yield None (它以前是yield gen.moment )休息一下,让事件循环运行其他任务,然后继续处理。 Example: 例:

@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}

Hopefully this helps you achieve your desired level of concurrency. 希望这可以帮助您达到所需的并发水平。

References 参考

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM