ink_Ocelot 发表于 2021-6-28 20:35:21

基于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]
查看完整版本: 基于logging实现的错误日志输出类装饰器