需求: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)))