tornado handler 调用
特性
在一次 tornado 请求中调用其他 tornado handler 中的方法, 比如 run 方法
引言
在后台开发中, 有时需要做一些功能的整合, 比如请求1,2,3 各自完成一项功能, 而现在有需求, 需要一次请求完成这三个功能,如果 handler 中请求逻辑与功能逻辑分离的很清晰(理想状态), 那直接调用功能逻辑就很方便, 但可能由于种种原因, handler 很有可能会有不少涉及到功能逻辑的代码。 只是对用户透明的话,也是可以由客户端来实现(比如发三次请求)。但可能后续还会有其他一些功能的整合, 以及网络延迟的问题, 所以最终确定由后台完成。
备注
flask 中有提供方法构造请求, 但 tornado 中没有提供, 需要自己实现
实现目标
实现一个方法, 传入 需要调用的 handler class, handler inputs, 以及一些其他 hanlder 中被调用函数所必须的参数, 返回 handler 调用的运算后的结果
实现思路
hander 的真实调用涉及相当多的准备工作, 错误处理以及收尾工作。 但 handler 中的方法的本质还是函数, 所以只要我们能提供这个函数运算所需要的数据, 那它就能正常的运算。 因为 python 是运行时语言,所以们并不需要去管那些 handler 中我们不需要调用到的方法所需要的数据而作为一个真正 hander 所必须的数据。 我们可以通过重写来避免这些真实 handler 所必须的数据。
示例
@coroutine
def doFakeHandle(handler, inputs,game, application):
class FakeHandle(handler):
def __init__(self, inputs, application, game):
self.application = application
self._game = game
self.input = inputs
self.write_list={}
@property
def game(self):
return self._game
def write(self, chunk):
self.write_list.update(chunk)
handler = FakeHandle(inputs, application, game)
try: yield handler.run()
except Exception, e:
if not isinstance(e, Return): raise e
raise Return(handler.write_list)
另外的实现思路:描述符和普通函数
python 新式类可以使用描述符,将需要复用的方法绑定到当前实例, 也可当成普通方法直接调用,不过都需要保证当前实例与复用方法中实例行为一致 。
示例
from aim_handler import AimClass
class NewHandler(BaseHandler):
@coroutine
def run(self):
self.input = input_data
yield AimClass.run.__get__(self, AimClass)()
# 也可以直接当成普通方法调用
# yield AimClass.run(self)
self.real_write()
def write(self, chunk):
pass
def real_write(self):
pass
注意
handler 方法的调用可能会涉及到 import 问题, 一个解决办法是把 import 语句放到调用 doFakeHandle 的函数中
因为历史原因使用,正常业务开发中都应该避免使用使用