python装饰器应用 一行代码为你的函数增加日志服务
1 什么是装饰器?
Python修饰器基于闭包原理,是赋予已存在的函数对象额外定制化功能的设计模式,使得代码简洁且易于维护,常用于插入日志、性能测试、权限校验等需求场景。例如某个具有登录功能的函数,现在希望添加数字签证核验功能,即可使用修饰器处理登录函数而无需变更登录函数的底层。Python语法糖@ 定义了修饰器
2 最通用的例子
def app(func):
def warp(*args, **kwargs):
print("正在执行功能1")
result = func(*args, **kwargs)
print("正在执行功能2")
return result
return warp
@app
def add(a, b):
return a + b
print(add(1,3))
*args 、**kwargs 用于接收被修饰函数的入口参数,*args、**kwargs分别用于将参数打包成tuple、dict给函数体调用。从上面可以看出,在不修改底层add函数的情况下,可以定制新功能。
3 实现日志打印修饰器
根据修饰器的原理,对上面的例子做小改动如下:
import logging
def log(func):
def warp(*args, **kwargs):
try:
result = func(*args, **kwargs)
return result
except Exception as e:
logging.error(e)
return warp
这里使用try-except 结构可以即使捕获异常信息输出到日志文件。
在某些应用场景,上面的结构还可以改进,比如Web服务可能要在输出日志后给前端反馈一个404代码,因此在增加一个定制化的返回内容err
def logger(err):
def log(func):
def warp(*args, **kwargs):
try:
result = func(*args, **kwargs)
return result
except Exception as e:
logging.error(e)
return err
return warp
return log
4 配置logging输出格式
import logging, os
'''
* %(asctime)s 即日志记录时间,精确到毫秒
* %(levelname)s 即此条日志级别
* %(filename)s 即触发日志记录的python文件名
* %(funcName)s 即触发日志记录的函数名
* %(lineno)s 即触发日志记录代码的行号
* %(message)s 即这项调用中的参数
'''
if not os.path.exists('Log.log'):
file = open('Log.log','w')
logging.basicConfig(
filename='Log.log',
format="%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s"
)
5 测试
@logger('加法环节出错了!')
def add(a, b):
return a + b
print(add(1, 2))
print(add(1, '2'))
2021-10-22 21:34:54,736 - ERROR - test.py - warp - 51 - unsupported operand type(s) for +: 'int' and 'str'
于是只要把上面说的logger函数封装成单独一个文件,在其他位置import logger并用修饰器修饰你希望增加日志功能的函数即可,非常方便
6 附:完整代码
import logging, os
'''
* %(asctime)s 即日志记录时间,精确到毫秒@breif:
* %(levelname)s 即此条日志级别@param[in]:
* %(filename)s 即触发日志记录的python文件名@retval:
* %(funcName)s 即触发日志记录的函数名
* %(lineno)s 即触发日志记录代码的行号
* %(message)s 即这项调用中的参数
'''
if not os.path.exists('Log.log'):
file = open('Log.log','w')
logging.basicConfig(
filename='Log.log',
format="%(asctime)s - %(levelname)s - %(filename)s - %(funcName)s - %(lineno)s - %(message)s"
)
'''
* @breif: 日志修饰器,为函数添加日志记录服务
* @param[in]: err -> 发生异常时返回的错误信息
* @retval: 加载日志服务的功能函数
'''
def logger(err):
def log(func):
def warp(*args, **kwargs):
try:
result = func(*args, **kwargs)
return result
except Exception as e:
logging.error(e)
return err
return warp
return log
@logger('出错了')
def add(a, b):
return a+b
print(add(1,'2'))
|