鱼C论坛

 找回密码
 立即注册
查看: 1621|回复: 0

[作品展示] 基于logging实现的错误日志输出类装饰器

[复制链接]
发表于 2021-6-28 20:35:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
这是一个当被装饰的方法出错时输出详细错误信息的模块
在导入模块后,输入 debugLogger.init()
然后在需要装饰的方法上加上@debugLogger.deco即可

模块关于日志输出位置的默认值是在主脚本运行的位置
这些值可以自行更改:
  1. debugLogger.init(
  2.         logPath=日志输出位置,
  3.         loggerName=logger名称)
  4. # 若直接使用debugLogger.init()将会使用默认值
复制代码


注意:该模块只能在类中的函数(或称方法)中使用,并且请确认你已经实例化该类

debugLogger.py
代码如下:
  1. # !/usr/bin/env python3
  2. # -*- coding:utf-8 -*-
  3. # @Author:InkOcelot
  4. # @Email:inkocelot@qq.com
  5. # @Version:1.0.0.0
  6. # @Update:Mon Jun 28 13:43:00 2021

  7. """
  8. 这是一个用于输出日志的模块
  9. 模块中的deco方法可用于装饰方法
  10. 并在错误时输出日志

  11. Usage:
  12.     class A:
  13.         @模块名.deco
  14.         def func(self):
  15.             ...
  16. """

  17. # Import Package
  18. try:
  19.     # 系统相关模块
  20.     import sys
  21.     # 错误回溯相关模块
  22.     import traceback
  23.     # 计时相关模块
  24.     import time
  25.     # 日志输出相关模块
  26.     import logging
  27.     from logging import handlers
  28. except ImportError as e:
  29.     print("无法加载模块:[%s]" % (e.args))
  30.     sys.exit()
  31. """
  32. __all__ = [
  33.     "init",
  34.     "deco"]
  35. """
  36. # Logger Class
  37. class Logger():
  38.     """日志输出模块"""
  39.     def __init__(self, logname, logger):
  40.         '''
  41.            指定保存日志的文件路径,以及调用文件
  42.            将日志存入到指定的文件中
  43.         '''

  44.         # 创建logger
  45.         self.logger = logging.getLogger(logger)
  46.         self.logger.setLevel(logging.DEBUG)

  47.         # handler:写入日志文件
  48.         fh = handlers.TimedRotatingFileHandler(filename=logname, when='D')
  49.         fh.setLevel(logging.DEBUG)

  50.         # handler:输出到控制台
  51.         ch = logging.StreamHandler()
  52.         ch.setLevel(logging.DEBUG)

  53.         # 定义handler的输出格式
  54.         formatter = logging.Formatter('''------------------------------\n%(asctime)s - %(name)s - %(levelname)s\n%(message)s''')
  55.         fh.setFormatter(formatter)
  56.         ch.setFormatter(formatter)

  57.         # 给logger添加handler
  58.         self.logger.addHandler(fh)
  59.         self.logger.addHandler(ch)

  60.     def getlog(self):
  61.         return self.logger

  62. # setLogger
  63. def init(logPath='./debuglog.log', loggerName="Logger"):
  64.     global logger
  65.     logger = Logger(logPath, loggerName).getlog()

  66. # Error Process Deco
  67. funcStack = []

  68. class EPro:
  69.     """装饰器模块"""
  70.      # 定义装饰器
  71.     @classmethod
  72.     def deco(self,func):
  73.         # 使用闭包的方式
  74.         def runFunc(self,*args,**kwargs):
  75.             try:
  76.                 funcStack.append({"class":func.__qualname__[:-(len(func.__name__)+1)],"func":func.__name__})
  77.                 func(self,*args,**kwargs)
  78.                 funcStack.pop()
  79.             except Exception:
  80.                 # 函数堆栈通告
  81.                 funcStackOutput = "#0\t类名\t方法名\n"
  82.                 count = 0
  83.                 for i in funcStack:
  84.                     count += 1
  85.                     funcStackOutput += "#{0}\t{1}\t{2}\n".format(count, i["class"], i["func"])
  86.                 funcStackOutput = funcStackOutput.replace("#{0}".format(count), "[{0}]".format(count))[:-1]

  87.                 #  自定义回溯通告
  88.                 exType,exValue,exTrace = sys.exc_info()
  89.                 errorDetail = "*** 详细信息 ***\n"
  90.                 for trace in traceback.extract_tb(exTrace):
  91.                     errorDetail += "在文件"{0}"中的第{1}行,在方法{2}中\n>>> {3}\n".format(
  92.                         trace.filename, trace.lineno, trace.name, trace.line)
  93.                 errorDetail += "错误类型:{0}\n错误描述:{1}".format(
  94.                     exType.__name__, exValue)
  95.                
  96.                 # 输出日志
  97.                 logger.error("*** 错误通告 ***\n发生时间:{0}\n具体时间戳:{1}\n类:{2}\n方法:{3}\n堆栈信息:\n{4}\n{5}".format(
  98.                     time.ctime(), time.time(), func.__qualname__[:-(len(func.__name__)+1)], func.__name__, funcStackOutput, errorDetail))

  99.                 # 完整退出
  100.                 sys.exit()
  101.         return runFunc

  102. # create global deco
  103. deco = EPro.deco

复制代码


示例:
  1. import debugLogger

  2. debugLogger.init()

  3. class A:
  4.     @debugLogger.deco
  5.     def func(self):
  6.         print("Hello World.")
  7.         c = a + b

  8. A().func()
复制代码


日志输出:
  1. ------------------------------
  2. 2021-06-28 20:14:03,191 - Logger - ERROR
  3. *** 错误通告 ***
  4. 发生时间:Mon Jun 28 20:14:03 2021
  5. 具体时间戳:1624882443.180995
  6. 类:A
  7. 方法:func
  8. 堆栈信息:
  9. #0        类名        方法名
  10. [1]        A        func
  11. *** 详细信息 ***
  12. 在文件"K:\xxx\debugLogger.py"中的第112行,在方法runFunc中
  13. >>> func(self,*args,**kwargs)
  14. 在文件"K:\xxx\test.py"中的第9行,在方法func中
  15. >>> c = a + b
  16. 错误类型:NameError
  17. 错误描述:name 'a' is not defined
复制代码


控制台输出:
BILL[BEX~]6H_%B)D~T(B.png
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-22 08:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表