# ============================================================ # 日志工具类 — 对标准库 logging 进行简单封装 # 提供控制台输出、文件输出、统一 message() 记录三个能力 # 避免在各处重复写 logger.handlers / FileHandler / Formatter 等样板代码 # ============================================================ import logging class Log: """ 简易日志封装类。 用法示例: log = Log('myapp', 'INFO') log.logFile('app.log') # 输出到文件 log.logConsol() # 同时输出到控制台 log.message('info', '启动成功') 设计要点: - 同一日志器重复 addHandler 会导致同一条日志输出多次, 所以 logFile / logConsol 里做了 handler 去重判断。 """ def __init__(self, name, lv): """ 构造日志器实例。 参数: name: 日志器名称,同名日志器是全局单例(logging.getLogger 内部维护) lv: 初始日志级别字符串,不区分大小写 可选值: 'DEBUG' / 'INFO' / 'WARNING' / 'ERROR' / 'CRITICAL' """ # ① 创建命名日志器 self.logName = logging.getLogger(name) # ② 设置日志级别(字符串转 logging.XXX 枚举) self.logName.setLevel(eval(f'logging.{lv.upper()}')) # ④ 定义统一的日志输出格式:时间 - 名称 - 级别 - 消息 self.formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) # 保存现有 handler 列表,方便后续去重 self.handlers = self.logName.handlers def logConsol(self): """将日志输出到控制台(stdout)。""" con_hand = logging.StreamHandler() # ③ 创建控制台处理器 con_hand.setFormatter(self.formatter) # 绑定格式 # 去重:避免重复添加同一个类型的 handler 导致日志重复打印 if 'StreamHandler' not in str(self.handlers): self.logName.addHandler(con_hand) # ⑤ 注册到日志器 def logFile(self, fileName): """ 将日志输出到指定文件(UTF-8 编码)。 参数: fileName: 日志文件名,例如 'log.txt' """ file_hand = logging.FileHandler(fileName, encoding='utf-8') # ③ 创建文件处理器 file_hand.setFormatter(self.formatter) # 去重:同一个文件 handler 只注册一次 if 'FileHandler' not in str(self.handlers): self.logName.addHandler(file_hand) # ⑤ 注册到日志器 def message(self, lv, mes): """ 按照指定级别输出一条日志。 参数: lv: 日志级别字符串(不区分大小写),可选 debug / info / warning / error / critical mes: 日志内容 """ lv = lv.lower() if lv == 'debug': self.logName.debug(mes) elif lv == 'info': self.logName.info(mes) elif lv == 'warning': self.logName.warning(mes) elif lv == 'error': self.logName.error(mes) elif lv == 'critical': self.logName.critical(mes) else: print('请输入正确的日志级别!')