自定义装饰器中的 Tornado 异步操作
Tornado asynchronous actions in custom decorator
我正在尝试使用 redis 和 tornadis 库为我的 Tornado 路由处理程序构建一个缓存装饰器。
这是我目前所拥有的:
def rediscache(route):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = yield redis.call("GET", "latest_info")
print(result)
func(*args, **kwargs)
return wrapper
return decorator
在我的路由处理程序中,我是这样使用它的:
class MainHandler(tornado.web.RequestHandler):
def initialize(self, db, redis):
self.db = db
self.quakes = self.db.quakes
self.redis = redis
@gen.coroutine
@rediscache('route_is_here')
def get(self):
''' ... handler logic here ... '''
问题是,如果我使用我的装饰器,我将不再看到从我的处理程序到网络的输出。如果不是...
result = yield redis.call("GET", "latest_info")
我愿意...
result = redis.call("GET", "latest_info")
然后我又开始在浏览器中看到输出,但这是正确的方法吗?这还是异步的吗?如果不是,正确的方法是什么?谢谢!
装饰器中的包装器应该是 gen.coroutine
如果你想 yield
协程:
def rediscache(route):
def decorator(func):
@tornado.gen.coroutine
@wraps(func)
def wrapper(*args, **kwargs):
result = yield redis.call("GET", "latest_info")
print(result)
if not result:
new = yield func(*args, **kwargs)
# save to
return wrapper
return decorator
您还需要将装饰器的顺序更改为:
@rediscache('route_is_here')
@gen.coroutine
def get(self):
''' ... handler logic here ... '''
编辑
装饰器顺序说明
@second
@first
def my_func():
pass
与
相同
my_func = second(first(my_func))
所以如果你想在装饰器中等待(产生)你原来的 get
,你必须通过协程,因此它必须在 rediscache
.
之前
关于装饰器的更多信息 - https://wiki.python.org/moin/PythonDecorators
我正在尝试使用 redis 和 tornadis 库为我的 Tornado 路由处理程序构建一个缓存装饰器。 这是我目前所拥有的:
def rediscache(route):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
result = yield redis.call("GET", "latest_info")
print(result)
func(*args, **kwargs)
return wrapper
return decorator
在我的路由处理程序中,我是这样使用它的:
class MainHandler(tornado.web.RequestHandler):
def initialize(self, db, redis):
self.db = db
self.quakes = self.db.quakes
self.redis = redis
@gen.coroutine
@rediscache('route_is_here')
def get(self):
''' ... handler logic here ... '''
问题是,如果我使用我的装饰器,我将不再看到从我的处理程序到网络的输出。如果不是...
result = yield redis.call("GET", "latest_info")
我愿意...
result = redis.call("GET", "latest_info")
然后我又开始在浏览器中看到输出,但这是正确的方法吗?这还是异步的吗?如果不是,正确的方法是什么?谢谢!
装饰器中的包装器应该是 gen.coroutine
如果你想 yield
协程:
def rediscache(route):
def decorator(func):
@tornado.gen.coroutine
@wraps(func)
def wrapper(*args, **kwargs):
result = yield redis.call("GET", "latest_info")
print(result)
if not result:
new = yield func(*args, **kwargs)
# save to
return wrapper
return decorator
您还需要将装饰器的顺序更改为:
@rediscache('route_is_here')
@gen.coroutine
def get(self):
''' ... handler logic here ... '''
编辑
装饰器顺序说明
@second
@first
def my_func():
pass
与
相同my_func = second(first(my_func))
所以如果你想在装饰器中等待(产生)你原来的 get
,你必须通过协程,因此它必须在 rediscache
.
关于装饰器的更多信息 - https://wiki.python.org/moin/PythonDecorators