在 Tornado 中缓存和重用函数结果 [英] Caching and reusing a function result in Tornado

查看:24
本文介绍了在 Tornado 中缓存和重用函数结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 Tornado 应用程序中包含一个昂贵的函数.功能返回几个输出,但由于遗留原因,这些输出被访问分别通过不同的处理程序.

I have an expensive function to include in my Tornado app. The function returns several outputs but, for legacy reason, these outputs are accessed separately through different handlers.

有没有办法只执行一次函数,将结果重新用于不同的处理程序并保留 Tornado 的异步行为?

Is there a way to execute the function only once, re-use the result for the different handlers and preserve Tornado's asynchronous behavior?

from tornado.web import RequestHandler
from tonado.ioloop import IOLoop

# the expensive function
def add(x, y):
    z = x + y
    return x, y, z

# the handlers that reuse the function
class Get_X(RequestHandler):
    def get(self, x, y):
        x, y, z = add(x, y) 
        return x

class Get_Y(RequestHandler):
    def get(self, x, y):
        x, y, z = add(x, y) 
        return y

class Get_Z(RequestHandler):
    def get(self, x, y):
        x, y, z = add(x, y) 
        return z

# the web service
application = tornado.web.Application([
    (r'/Get_X', Get_X),
    (r'/Get_Y', Get_Y),
    (r'/Get_Z', Get_Z),
])

application.listen(8888)
IOLoop.current().start()

我考虑过将函数的结果缓存在字典中,但我不确定如何让其他两个处理程序等待,而第一个处理程序创建一个字典条目.

I thought about about caching the result of the function in a dictionary, but I'm not sure on how to make the two other handlers wait, while the first one creates a dictionary entry.

推荐答案

Tornado Futures 是可重复使用的,因此您可以在生成它之前简单地保存 Future.许多现成的缓存装饰器(如 python 3.2 的 functools.lru_cache 就可以工作,如果你把它们放在 @gen.coroutine 的前面:

Tornado Futures are reusable, so you can simply save the Future before yielding it. Many off-the-shelf caching decorators (like python 3.2's functools.lru_cache will just work if you put them in front of @gen.coroutine:

import functools
from tornado import gen
from tornado.ioloop import IOLoop

@functools.lru_cache(maxsize=100)
@gen.coroutine
def expensive_function():
    print('starting expensive_function')
    yield gen.sleep(5)
    return 1, 2, 3

@gen.coroutine
def get_x():
    print('starting get_x')
    x, y, z = yield expensive_function()
    return x

@gen.coroutine
def get_y():
    print('starting get_y')
    x, y, z = yield expensive_function()
    return y

@gen.coroutine
def get_z():
    print('starting get_z')
    x, y, z = yield expensive_function()
    return z

@gen.coroutine
def main():
    x, y, z = yield [get_x(), get_y(), get_z()]
    print(x, y, z)

if __name__ == '__main__':
    IOLoop.current().run_sync(main)

打印:

starting get_x
starting expensive_function
starting get_y
starting get_z
finished expensive_function
1 2 3

这篇关于在 Tornado 中缓存和重用函数结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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