用一个简单的Python发生器作为龙卷风异步处理程序协同例程? [英] Using a simple python generator as a co-routine in a Tornado async handler?
问题描述
我有产生文本块一个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屋!