基于Python编写简单实用的日志装饰器
作者:Ckend 发布时间:2022-10-09 01:21:51
在写代码的时候,往往会漏掉日志这个关键因素,导致功能在使用的时候出错却无法溯源。
其实,只需要写一个非常简单的日志装饰器,我们就能大大提升排查问题的效率。
1.简陋版装饰器
写一个装饰器非常简单,因为本质上装饰器就是一个返回函数的“高阶”函数而已:
1) 函数作为参数传递进装饰器。
2) 装饰器内定义一个函数,处理作为参数传递进来的函数。
3) 返回这个装饰器内定义的函数
import datetime
def log(func):
"""
日志装饰器,简单记录函数的日志
Args:
func (function): 函数
"""
def inner(*args):
timestamp = str(datetime.datetime.now()).split(".")[0]
res = func(*args)
print(f"[{timestamp}] ({func.__name__}) {args} -> {res}")
return res
return inner
用一下试试看:
@log
def pluser(a, b):
return a + b
pluser(1, 2)
效果如下:
虽然这样可以实现我们所需要的功能,但其实有很大的优化空间。
2.普通版装饰器
第一版代码中有一个显而易见的问题,装饰器内定义的处理函数不支持kwargs,而在装饰器中支持kwargs仅仅是举手之劳而已。
第二个问题是,生成时间戳的时候采用字符串截取的形式,这种形式过于粗暴。其实可以使用strftime做字符串转换。
修改如下:
import datetime
def log(func):
"""
日志装饰器,简单记录函数的日志
Args:
func (function): 函数
"""
def inner(*args, **kwargs):
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
res = func(*args, **kwargs)
print(f"[{timestamp}] ({func.__name__}) {args} -> {res}")
return res
return inner
似乎优化得差不多了,不过依然存在改进空间。
3.优化版装饰器
在前两版代码中,我们使用print进行日志输出,其实这种处理日志的方式并不标准。
使用logging模块控制日志输出是一个更好地选择。
为了使用logging模块记录日志,我们需要先配置好logging相关的选项。
1) 首先,生成一个日志记录器,并配置日志等级:
import logging
# 获取日志记录器,配置日志等级
logger = logging.getLogger(__name__)
logger.setLevel('DEBUG')
2) 配置日志格式、增加handler控制输出流:
# 默认日志格式
formatter = logging.Formatter("%(asctime)s - [%(levelname)s] - %(message)s")
# 输出到控制台的handler
chlr = logging.StreamHandler()
# 配置默认日志格式
chlr.setFormatter(formatter)
此处可以设置handler所需要处理的日志等级,没有设置则默认使用logger自身的Level,即DEBUG等级。
3) 最后,将此handler加入到日志记录器内:
# 日志记录器增加此handler
logger.addHandler(chlr)
logging 完整配置如下:
import logging
# 获取日志记录器,配置日志等级
logger = logging.getLogger(__name__)
logger.setLevel('DEBUG')
# 默认日志格式
formatter = logging.Formatter("%(asctime)s - [%(levelname)s] - %(message)s")
# 输出到控制台的handler
chlr = logging.StreamHandler()
# 配置默认日志格式
chlr.setFormatter(formatter)
# 日志记录器增加此handler
logger.addHandler(chlr)
使用的时候非常简单,就是把print换成logger.debug即可:
def log(func):
"""
日志装饰器,简单记录函数的日志
Args:
func (function): 函数
"""
def inner(*args, **kwargs):
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
res = func(*args, **kwargs)
logger.debug(f"func: {func.__name__} {args} -> {res}")
return res
return inner
效果如下:
这样,一个比较完善的日志装饰器就完成了。
附常用的日志等级配置:
来源:https://mp.weixin.qq.com/s/0lbhIAcBCjXNnh49wInYvA
猜你喜欢
- 现在我们已经很熟悉Django的MTV模式了。模板(template)负责如何去展示数据,而视图(view)负责筛选出正确的数据。因此通常来
- 本文实例讲述了Python实现求两个数组交集的方法。分享给大家供大家参考,具体如下:一、题目给定两个数组,编写一个函数来计算它们的交集。例1
- 锟拷码和口字码说到乱码问题就不得不提到锟斤拷,这算是非常常见的一种乱码形式,那么它到底是经过何种错误操作产生的呢?下面我们一步步探究。看一个
- 本文实例讲述了Python使用minidom读写xml的方法。分享给大家供大家参考。具体分析如下:一 python提供的xml支持2种工业标
- 本文实例讲述了Python使用django获取用户IP地址的方法。分享给大家供大家参考。具体如下:函数实现:def get_client_i
- 由于ajax在跨域的访问上有问题,目前最好的方法是做代理.写了个代理程序和心得为了做ajax的代理,研究了下服务器端的xmlhttp并和客户
- 这片文章大体概括了一些设计网页中的大问题。希望能给你做下一个网页时给予一些儿启发。1、记住:你能掌控的时间是有限的我仅仅用4秒钟就能浏览完平
- 前言在python中,通过内嵌集成re模块,程序媛们可以直接调用来实现正则匹配。正则表达式模式被编译成一系列的字节码,然后由用C编写的匹配引
- 这个收藏本站、设为首页代码相信每个网站都会用到,这么常用的代码,网络上流行的一般是很多年前的代码版本,只有兼容IE,对其它浏览器没有考虑,下
- 先把这个script加到你的页面里:http://code.google.com/p/doufu/source/browse/trunk/n
- 一个申请单可以包含N个项目,添加申请单时就需要动态加入代码了。 动态Table表格 <table border="0&quo
- 同时,关于datetime也是简单介绍。因为有很多东西需要自己去使用,去查帮助才最有效。例子:计算上一个星期五并输出。解答:import d
- 对于一个内容页的文章来说,如果这个文章内容过长或是其中有分类(排行),那么进行分页阅读无疑是最好的选择。如果一个文章内容不涉及分类,比如小说
- 采用双重循环。把图片进行“.”分割后名字问前面部分,那其余数据库中的 图片路径记录进行对比 采用vb的InStr函数 如果存在的话返回值&g
- 交换变量 x = 6y = 5x, y = y, xprint x>>> 5print y>>>
- 这篇文章主要给大家介绍了利用Thinkphp结合ajaxFileUpload实现异步图片传输的方法,文中给出了详细的示例代码,对大家具有一定
- 问题:数据库实际大小为600MB, 日志文件实际大小为33MB, 但日志文件占用空间为2.8GB!试了多种方式,SHIRNK DATABAS
- 有时候我们需要程序截图文章中的部分字符作为摘要显示出来,这时我们一般是只希望提取的字符串是纯文本的,没有如何html标签,如果我们章节用le
- 进度条的作用就是提示用户进度信息。可以有两种方式:1)提示完成度比如,正在安装程序的进度,一般是从0%到100%。2)提示正在进行处理比如正
- 序言:刚结束公司的三个月试用期,意味着我即将正式步入社会成为广大从事IT行业的一员。作为一个编程小白,无论从技术层面还是知识层面都是比较薄弱