需求:api
有package db_api,其下有不少 module 如 plane.py ship.py ufo.py。這些module內定義了方法如 plane.fly(), ship.float(),ufo.siu()。如今但願有一個裝飾器來給裝飾這些函數,讓其打印log,log中包含調用的參數以及return。app
解決辦法函數
首先定義 decoratorcode
def db_log(func): @functools.wraps(func) def wrapper(*args, **kwargs): func_name = str(func) if func else '' log_args = str(args) if args else '' log_kwargs = str(kwargs) if kwargs else '' eventLog.info("call %s" % func_name) eventLog.info("args are %s" % log_args) eventLog.info("kwargs are %s " % log_kwargs) ret = func(*args, **kwargs) log_ret = str(ret) if ret else '' eventLog.info("ret are %s" % log_ret) return ret return wrapper
這沒什麼問題,問題是,接下來你要手動的去裝飾以前的每個方法如 fly 等。 這裏咱們用一段代碼動態的patch 這些函數ip
在db_api/init.py 中會import 全部moduleget
import plane import ufo import ship
而後用下面的代碼動態裝飾it
for module_obj in dir(): if isinstance(eval(module_obj),type(plane)) and eval(module_obj).__package__ == 'db_api': # Patch call ables module_obj = eval(module_obj) for func_obj in dir(module_obj): if callable(getattr(module_obj, func_obj)) and not func_obj.startswith('_') and isinstance(getattr(module_obj, func_obj),type(lambda x: x)): # func_obj = db_log(func_obj) setattr(module_obj,func_obj,db_log(getattr(module_obj, func_obj)))