繁体   English   中英

Tornado异步调用函数

[英]Tornado async call to a function

我正在使用Python + Tornado创建一个Web应用程序,它基本上为用户提供文件。 我没有数据库。

如果文件可用,则直接拾取和提供文件,如果没有,则立即生成。

我希望以异步方式提供客户端,因为某些文件可能已经可用,而其他文件需要生成(因此需要等待,我不希望它们阻止其他用户)。

我有一个管理文件选择或生成的类,我只需要从Tornado调用它。

实现这一目标的最佳方法(在CPU和RAM上最有效)是什么? 我应该使用线程吗? 一个子流程? 一个简单的gen.Task喜欢这个吗?

另外,我希望我的实现能够在Google App Engines上运行(我认为它们不允许生成子流程?)。

我对异步Web服务比较新,所以欢迎任何帮助。

我找到了我的问题的答案:genTask示例确实是实现异步调用的最佳方式,这是因为该示例确实使用了Python协程 ,乍一看我并不理解,因为我认为yield只用于返回生成器的值。

具体例子:

class MyHandler(tornado.web.RequestHandler):

    @asynchronous
    @gen.engine
    def get(self):
        response = yield gen.Task(self.dosomething, 'argument')

这里重要的是两件事的结合:

  • yield ,实际上产生了一个协程(或伪线程,这是非常有效的,并且是高度并发友好的)。 http://www.python.org/dev/peps/pep-0342/

  • gen.Task()是一个非阻塞(异步)函数,因为如果你在一个阻塞函数上产生一个协程,它就不会是异步的。 gen.Task()由Tornado提供,专门用于处理Python的协程语法。 更多信息: http//www.tornadoweb.org/documentation/gen.html

因此,使用协同程序在Python中进行异步调用的规范示例:

response = yield non_blocking_func(**kwargs)

现在文档有解决方案。

简单的例子:

import os.path
import tornado.web
from tornado import gen

class MyHandler(tornado.web.RequestHandler):

    @gen.coroutine
    def get(self, filename):
        result = yield self.some_usefull_process(filename)
        self.write(result)

    @gen.coroutine
    def some_usefull_process(self, filename):
        if not os.path.exists(filename):
            status = yield self.generate_file(filename)
            result = 'File created'
        else:
            result = 'File exists'

        raise gen.Return(result)

    @gen.coroutine
    def generate_file(self, filename):
        fd = open(filename, 'w')
        fd.write('created')
        fd.close()

暂无
暂无

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

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