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))
# 正在执行功能1
# 正在执行功能2
# 4
*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)) # 输出3
# 异常情况
print(add(1, '2')) # 输出“加法环节出错了!”
# Log.log中的记录
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: 加载日志服务的功能函数
**收集整理了一份《2024年最新Python全套学习资料》免费送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。**






**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Python知识点,真正体系化!**
**了解详情:https://docs.qq.com/doc/DSnl3ZGlhT1RDaVhV**