使用简单的 python 生成器作为 Tornado 异步处理程序中的协同例程?
我有一个 python 生成器函数,它可以生成文本块。我想为 tornado.web.RequestHandler
子类编写一个 get
方法,该方法将迭代生成器,将块写入响应中。
由于这是 Tornado,并且生成器可能需要一秒钟的时间来处理,因此我认为最好使处理程序异步,使用此生成器作为协同例程,并在每个块之后将控制权传递给 IOLoop。然而,我不知道如何做到这一点。
这是我的示例(阻塞)代码:
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
如何使该处理程序异步工作?
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.
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.
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是您所描述内容的基本版本。为了避免阻塞,您可以通过回调函数将生成器传递给 IOLoop。这里的技巧是,由于您没有使用执行实际 IO 的进程,因此没有操作系统级别的进程/文件处理程序可以通过 add_handler 添加到 IOLoop,因此您可以使用简单的 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 simpleadd_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.还可以使用新的 tornado 的 gen 接口来进行异步进程:
It is also possible to use the new tornado's gen interface to async processes: