Python3使用logging模块实现按日期动态生成日志文件问题咨询
解决方案
你现有代码的问题在于,仅在初始化logger的阶段调用了一次get_file_handler,生成的文件路径是程序启动时的日期,后续运行过程中不会主动检测日期变更更新文件路径,因此日期切换后仍会写入旧文件。
要实现你要求的直接按当前日期生成对应文件名写入、不经过固定文件名重命名的逻辑,可以通过自定义logging的旋转Handler实现,修改后的可运行代码如下:
import logging import coloredlogs import platform import sys import os from datetime import datetime from logging.handlers import BaseRotatingHandler FORMATTER = logging.Formatter("%(asctime)s : %(hostname)s : %(name)s : %(levelname)s : %(message)s") LOG_FILE = os.environ['RMQ_DISPACHER_LOGFILE'] NICKNAME = os.environ['LOGNICKNAME'] class HostnameFilter(logging.Filter): hostname = platform.node() def filter(self, record): record.hostname = HostnameFilter.hostname return True # 自定义按天动态生成文件名的Handler class DailyDynamicFileHandler(BaseRotatingHandler): def __init__(self, log_dir, nickname, encoding=None, delay=False): self.log_dir = log_dir self.nickname = nickname self.current_date = datetime.now().strftime('%Y%m%d') # 生成初始日志文件名 filename = self._get_current_filename() super().__init__(filename, mode='a', encoding=encoding, delay=delay) def _get_current_filename(self): return f"{self.log_dir}/{self.nickname}_{self.current_date}.log" def shouldRollover(self, record): # 检查当前日期是否和上次写入的日期一致 now_date = datetime.now().strftime('%Y%m%d') if now_date != self.current_date: self.current_date = now_date return True return False def doRollover(self): # 关闭旧的文件流 if self.stream: self.stream.close() self.stream = None # 更新为新日期的文件名 self.baseFilename = self._get_current_filename() # 打开新的文件流 if not self.delay: self.stream = self._open() def get_console_handler(): console_handler = logging.StreamHandler(sys.stdout) console_handler.addFilter(HostnameFilter()) console_handler.setFormatter(FORMATTER) return console_handler def get_file_handler(): # 替换为自定义的Handler file_handler = DailyDynamicFileHandler(LOG_FILE, NICKNAME) file_handler.addFilter(HostnameFilter()) file_handler.setFormatter(FORMATTER) return file_handler def get_logger(logger_name): logger = logging.getLogger(logger_name) logger.setLevel(logging.DEBUG) logger.addHandler(get_console_handler()) logger.addHandler(get_file_handler()) logger.propagate = False coloredlogs.install(logger=logger) return logger
实现说明
- 自定义的
DailyDynamicFileHandler继承了logging官方提供的BaseRotatingHandler基础旋转类,每次写入日志前都会调用shouldRollover方法校验当前日期是否发生变化 - 检测到日期变更后自动触发
doRollover逻辑,关闭旧日志文件流,按你指定的命名规则生成新日期的日志文件并打开新流,完全符合你的使用要求 - 兼容你原有代码中的HostnameFilter、日志格式配置和coloredlogs的能力,不需要修改上层调用logger的业务代码
如果需要自动清理过期日志,可以在doRollover方法中补充扫描日志目录、删除超过指定保留天数的旧文件的逻辑,避免磁盘占用过高。
内容的提问来源于stack exchange,提问作者Éric
相关产品推荐
相关产品推荐

