首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用简单的python生成器作为Tornado异步处理程序中的协同例程?

使用简单的python生成器作为Tornado异步处理程序中的协同例程?
EN

Stack Overflow用户
提问于 2012-01-11 08:45:48
回答 2查看 6.6K关注 0票数 16

我有一个可以生成文本块的python生成器函数。我想为tornado.web.RequestHandler子类编写一个get方法,它将在生成器上迭代,并在响应过程中将块写出。

由于这是Tornado,而且生成器可能需要超过一秒的时间来处理,我认为让处理程序异步会更好,使用此生成器作为协同例程,并在每个块之后将控制传递给IOLoop。然而,我不知道该怎么做。

下面是我的示例(阻塞)代码:

代码语言:javascript
复制
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

怎样才能让这个处理程序异步工作呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-01-11 23:30:25

以下是您所描述的内容的基本版本。为了避免阻塞,您可以通过回调函数将生成器传递给IOLoop。这里的诀窍在于,由于您没有使用执行实际IO的进程,因此没有操作系统级别的进程/文件处理程序可以通过add_handler添加到IOLoop中,因此您可以使用一个简单的add_callback调用,并在回调函数中重复调用它,以将该函数保留在IOLoop回调队列中,直到生成器完成为止。

代码语言:javascript
复制
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()
票数 16
EN

Stack Overflow用户

发布于 2012-01-12 02:19:04

还可以使用新的tornado's gen接口来异步进程:

代码语言:javascript
复制
import tornado.httpserver
import tornado.ioloop
import tornado.web
import tornado.gen

class TextHandler(tornado.web.RequestHandler):

    @tornado.web.asynchronous
    @tornado.gen.engine
    def get(self):

        def cb(it, callback):
            try:
                value = it.next()
            except StopIteration:
                value = None
            callback(value)

        it = self.generate_text(1000)
        while True:
            response = yield tornado.gen.Task(cb, it)
            if response:
                self.write(response)
            else:
                break
        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()
票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8812715

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档