用一个简单的Python发生器作为龙卷风异步处理程序协同例程? [英] Using a simple python generator as a co-routine in a Tornado async handler?

查看:143
本文介绍了用一个简单的Python发生器作为龙卷风异步处理程序协同例程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有产生文本块一个Python发生器功能。我想编写一个 tornado.web.RequestHandler 子类,它会遍历发电机,写作 GET 方法该块出来,因为它去响应。

I have a python generator function which yields chunks of text. I would like to write a get method for a tornado.web.RequestHandler subclass that will iterate over the generator, writing the chunks out to the response as it goes.

由于这是龙卷风,而且由于发电机可以接管第二个来处理,我认为这将是很好使处理异步,使用这种发电机作为共同常规和假冒控制到IOLoop每块之后。但是,我不能让首长或尾巴如何做到这一点。

Since this is Tornado, and since the generator may take over a second to process, I thought it would be nice to make the handler asynchronous, using this generator as a co-routine and passing off control to the IOLoop after every chunk. However, I can't make heads or tails of how to do this.

下面是我的例子(阻塞)code:

Here's my example (blocking) code:

class TextHandler(web.RequestHandler):
    @web.asynchronous
    def get(self, n):
        generator = self.generate_text(100000)
        # Clearly, this will block. How to make it asynchronous?
        for text in generator:
            self.write(text)

    def generate_text(n):
        for x in xrange(n):
            if not x % 15:
                yield "FizzBuzz\n"
            elif not x % 5:
                yield "Buzz\n"
            elif not x % 3:
                yield "Fizz\n"
            else:
                yield "%s\n" % x

我怎样才能让这个处理异步工作?

How can I make this handler work asynchronously?

推荐答案

以下是你所描述的基本版本。为了避免阻塞,您可以通过一个回调函数传递您的发电机给IOLoop。这里的技巧是,因为你没有使用一个过程,它实际IO等没有操作系统级别进程/文件处理程序添加到IOLoop通过 add_handler ,你可以改用一个简单的 add_callback 电话,多次拨打其从回调函数中保持​​功能在IOLoop回调队列中,直到发电机已经完成。

Here's a basic version of what you are describing. To avoid blocking you can pass your generator to the IOLoop via a callback function. The trick here is since you are not using a process that does actual IO and so has no os level process/file handler to add to the IOLoop via add_handler, you can instead use a simple add_callback call and call it repeatedly from within the callback function to keep the function in the IOLoop callback queue until the generator has finished.

import tornado.httpserver
import tornado.ioloop
import tornado.web

class TextHandler(tornado.web.RequestHandler):
    @tornado.web.asynchronous
    def get(self):
        self.generator = self.generate_text(1000)
        tornado.ioloop.IOLoop.instance().add_callback(self.loop)

    def loop(self):
        try:
            text = self.generator.next()
            self.write(text)
            tornado.ioloop.IOLoop.instance().add_callback(self.loop)
        except StopIteration:
            self.finish()

    def generate_text(self, n):
        for x in xrange(n):
            if not x % 15:
                yield "FizzBuzz\n"
            elif not x % 5:
                yield "Buzz\n"
            elif not x % 3:
                yield "Fizz\n"
            else:
                yield "%s\n" % x

application = tornado.web.Application([
    (r"/text/", TextHandler),
])

http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8888)
tornado.ioloop.IOLoop.instance().start()

这篇关于用一个简单的Python发生器作为龙卷风异步处理程序协同例程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆