让所有使用logging的package使用logger方式
logging是Python中的日志系统,非常强大。但不少模块只是在import后简单的使用logging.debug|warning|error|exception来处理,对于一个规模稍微大一点的项目来说,最后日志中混乱的记录简直就是噩梦。
logging是提供了这种问题的解决方案的——logger。只需要logging.getLogger就可以获取一个名字的logger,并且支持以英文小数点进行分级控制。
但是第三方库却又很多不这样用的。没错,说的就是你oauthlib。每次生成签名的时候还都要debug一堆。
当然,简单的把代码改为logger方式是可行的,但是不是个好方法:
- 工作量很大,你只能手动搜索使用了logging的模块,肉眼分析使用方式,然后修改。
- 第三方库日后的更新会带来很多问题。哪怕用了git的分支,merge的时候也不是永远100%正确的。
所以理想的方式,是直接替换logging模块里的debug|warning|error|exception函数,让调用这些函数时就自动使用logger方式。
下面直接给出我的实现:
def logger_wrap(func):
def logger_wrapped(*args, **kwargs):
caller_frame = inspect.currentframe().f_back
caller_name = caller_frame.f_globals["__package__"]
logger = logging.getLogger(caller_name)
getattr(logger, func.__name__)(*args, **kwargs)
return logger_wrapped
for func_name in ("critical", "error", "exception", "warn", "warning", "info", "debug", "log"):
setattr(logging, func_name, logger_wrap(getattr(logging, func_name)))
注意不能简单的使用__name__来获取,必须用inspect来实现。这个实现借鉴了Retreiving/Printing execution context这里的思路。