基于logging实现的错误日志输出类装饰器
这是一个当被装饰的方法出错时输出详细错误信息的模块在导入模块后,输入 debugLogger.init()
然后在需要装饰的方法上加上@debugLogger.deco即可
模块关于日志输出位置的默认值是在主脚本运行的位置
这些值可以自行更改:
debugLogger.init(
logPath=日志输出位置,
loggerName=logger名称)
# 若直接使用debugLogger.init()将会使用默认值
注意:该模块只能在类中的函数(或称方法)中使用,并且请确认你已经实例化该类
debugLogger.py
代码如下:
# !/usr/bin/env python3
# -*- coding:utf-8 -*-
# @Author:InkOcelot
# @Email:inkocelot@qq.com
# @Version:1.0.0.0
# @Update:Mon Jun 28 13:43:00 2021
"""
这是一个用于输出日志的模块
模块中的deco方法可用于装饰方法
并在错误时输出日志
Usage:
class A:
@模块名.deco
def func(self):
...
"""
# Import Package
try:
# 系统相关模块
import sys
# 错误回溯相关模块
import traceback
# 计时相关模块
import time
# 日志输出相关模块
import logging
from logging import handlers
except ImportError as e:
print("无法加载模块:[%s]" % (e.args))
sys.exit()
"""
__all__ = [
"init",
"deco"]
"""
# Logger Class
class Logger():
"""日志输出模块"""
def __init__(self, logname, logger):
'''
指定保存日志的文件路径,以及调用文件
将日志存入到指定的文件中
'''
# 创建logger
self.logger = logging.getLogger(logger)
self.logger.setLevel(logging.DEBUG)
# handler:写入日志文件
fh = handlers.TimedRotatingFileHandler(filename=logname, when='D')
fh.setLevel(logging.DEBUG)
# handler:输出到控制台
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# 定义handler的输出格式
formatter = logging.Formatter('''------------------------------\n%(asctime)s - %(name)s - %(levelname)s\n%(message)s''')
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# 给logger添加handler
self.logger.addHandler(fh)
self.logger.addHandler(ch)
def getlog(self):
return self.logger
# setLogger
def init(logPath='./debuglog.log', loggerName="Logger"):
global logger
logger = Logger(logPath, loggerName).getlog()
# Error Process Deco
funcStack = []
class EPro:
"""装饰器模块"""
# 定义装饰器
@classmethod
def deco(self,func):
# 使用闭包的方式
def runFunc(self,*args,**kwargs):
try:
funcStack.append({"class":func.__qualname__[:-(len(func.__name__)+1)],"func":func.__name__})
func(self,*args,**kwargs)
funcStack.pop()
except Exception:
# 函数堆栈通告
funcStackOutput = "#0\t类名\t方法名\n"
count = 0
for i in funcStack:
count += 1
funcStackOutput += "#{0}\t{1}\t{2}\n".format(count, i["class"], i["func"])
funcStackOutput = funcStackOutput.replace("#{0}".format(count), "[{0}]".format(count))[:-1]
#自定义回溯通告
exType,exValue,exTrace = sys.exc_info()
errorDetail = "*** 详细信息 ***\n"
for trace in traceback.extract_tb(exTrace):
errorDetail += "在文件\"{0}\"中的第{1}行,在方法{2}中\n>>> {3}\n".format(
trace.filename, trace.lineno, trace.name, trace.line)
errorDetail += "错误类型:{0}\n错误描述:{1}".format(
exType.__name__, exValue)
# 输出日志
logger.error("*** 错误通告 ***\n发生时间:{0}\n具体时间戳:{1}\n类:{2}\n方法:{3}\n堆栈信息:\n{4}\n{5}".format(
time.ctime(), time.time(), func.__qualname__[:-(len(func.__name__)+1)], func.__name__, funcStackOutput, errorDetail))
# 完整退出
sys.exit()
return runFunc
# create global deco
deco = EPro.deco
示例:
import debugLogger
debugLogger.init()
class A:
@debugLogger.deco
def func(self):
print("Hello World.")
c = a + b
A().func()
日志输出:
------------------------------
2021-06-28 20:14:03,191 - Logger - ERROR
*** 错误通告 ***
发生时间:Mon Jun 28 20:14:03 2021
具体时间戳:1624882443.180995
类:A
方法:func
堆栈信息:
#0 类名 方法名
A func
*** 详细信息 ***
在文件"K:\xxx\debugLogger.py"中的第112行,在方法runFunc中
>>> func(self,*args,**kwargs)
在文件"K:\xxx\test.py"中的第9行,在方法func中
>>> c = a + b
错误类型:NameError
错误描述:name 'a' is not defined
控制台输出:
页:
[1]