【发布时间】:2013-09-26 05:49:24
【问题描述】:
from tornado import web, gen
import tornado, time
class CoroutineFactorialHandler(web.RequestHandler):
@web.asynchronous
@gen.coroutine
def get(self, n, *args, **kwargs):
n = int(n)
def callbacker(iterator, callback):
try:
value = next(iterator)
except StopIteration:
value = StopIteration
callback(value)
def factorial(n):
x = 1
for i in range(1, n+1):
x *= i
yield
yield x
iterator = factorial(n)
t = time.time()
self.set_header("Content-Type", "text/plain")
while True:
response = yield gen.Task(callbacker, iterator)
#log.debug("response: %r" %response)
if response is StopIteration:
break
elif response:
self.write("took : %f sec" %(time.time() - t))
self.write("\n")
self.write("f(%d) = %d" %(n, response))
self.finish()
application = tornado.web.Application([
(r"^/coroutine/factorial/(?P<n>\d+)", CoroutineFactorialHandler),
#http://localhost:8888/coroutine/factorial/<int:n>
])
if __name__ == "__main__":
application.listen(8888)
ioloop = tornado.ioloop.IOLoop.instance()
ioloop.start()
21 行被拉出 以上是简单的阶乘计算器。它以生成器的方式循环 N 次。
问题是,当这段代码执行时,它会阻塞整个龙卷风。
我想要实现的是为 tornado 编写一些帮助程序,将生成器视为协程,因此可以以异步方式服务请求。 (我已阅读Using a simple python generator as a co-routine in a Tornado async handler?)
为什么简单的增加和乘以 n 循环会阻止整个龙卷风?
edit :我编辑了代码以包含整个应用程序,您可以运行和测试它。 我在 python 2.7 上运行 tornado 3.1.1
【问题讨论】:
-
你的
get真的可以接受这样的论点吗? (当我在 Python 2.7.2 上使用 Tornado 3.1.1 尝试此操作时,我得到一个TypeError: get() takes at least 2 arguments (1 given)。我认为这不是你的问题——如果我将其更改为不使用 args 并使用self.get_argument(n),我想无论如何它都说明了你的问题。但我不确定。那么,这实际上是你的代码吗?如果是,你使用的是哪个版本? -
@abarnert 我编辑了代码。如果您仍然感兴趣,请看一下。
-
啊,我明白了,您想使用路径组件,而不是查询字符串。说得通。无论如何,我认为这不是你的问题——正如我所说,我使用
self.get_argument读取查询字符串的编辑版本展示了相同的行为。我没有答案给你。有机会我会仔细研究一下,但希望其他比我使用 Tornado 的人会先出现。
标签: python asynchronous tornado coroutine