在tornado中实现一个异步缓存装饰器
# 装饰器部分如下
def get_and_cache(expire_seconds=60 * 60 * 24):
    """key可能需要参数拼接不能直接从参数传入,从被装饰函数参数中获取"""
    def _cache(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            key = kwargs.pop("cache_key", None)
            if key:
                result = Redis.get(key)
                if result:
                    return json.loads(result)
            """
            # 调用tornado的异步装饰器在同步函数中处理异步方法(tornado中哪怕func不是异步的或者func已经被coroutine装饰)
            # 如果在其他框架或脚本,可以使用asyncio处理,比如
            asyncio.run(asyncio.wait(func(*args, **kwargs)))
            """
            result = yield gen.coroutine(func)(*args, **kwargs)
            Redis.set(key, json.dumps(result), expire_seconds=expire_seconds)
            return result
        return wrapper
    return _cache
# 使用
class A:
    @staticmethod
    @gen.coroutine
    @get_and_cache(expire_seconds=60 * 60 * 24)
    def func(*args, **kwargs):
        """
        业务部分
        """
        result = "pass"
        raise gen.Return(result)
cc = A.func(xxx, xxx, cache_key="xxx")
print(cc)