tornado handler 方法復用
- 2020 年 1 月 19 日
- 筆記
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 的函數中
因為歷史原因使用,正常業務開發中都應該避免使用使用