# !/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@contact: [email protected]
@time: 2023/2/11 17:41 $
@desc:
"""
import os
import logging
from logging.handlers import TimedRotatingFileHandler, RotatingFileHandler
from queue import Queue
class LogParent():
def __init__(self,sign="root", file="./log/log.log"):
os.makedirs(os.path.split(file)[0], exist_ok=True)
self.sign = sign
self.filename = file
self.logger = None
self.recode_file = True
# T,S
self.mode = "T"
self.maxBytes = 100
class SingleLogProcess(LogParent):
"""
单线程
"""
def __init__(self, sign="root", file="./log/log.log"):
super(SingleLogProcess, self).__init__(sign,file)
self._init()
def get_log(self):
if not self.logger:
self._init()
return self.logger
def _init(self):
# 创建日志器对象
logger = logging.getLogger(self.sign)
# 设置logger可输出日志级别范围
logger.setLevel(logging.INFO)
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
# 添加控制台handler,用于输出日志到控制台
console_handler = logging.StreamHandler()
# 添加日志文件handler,用于输出日志到文件中
if self.recode_file:
if self.mode == "T":
handler = TimedRotatingFileHandler(filename=self.filename,
encoding='UTF-8',
when="D",
interval=1,
backupCount=7
)
elif self.mode == "S":
handler = RotatingFileHandler(filename=self.filename,
encoding='UTF-8',
maxBytes=self.maxBytes,
backupCount=7
)
else:
raise ValueError("mode not support : {}".format(self.mode))
logger.addHandler(handler)
handler.setFormatter(formatter)
# 将handler添加到日志器中
logger.addHandler(console_handler)
# 设置格式并赋予handler
console_handler.setFormatter(formatter)
self.logger = logger
return logger
class MultiLogProcess(LogParent):
"""
支持 多线程
"""
def __init__(self, sign="root", file="./log/log.log"):
super(MultiLogProcess, self).__init__(sign,file)
# 创建队列对象
self.log_queue = Queue()
self._init()
def get_log(self):
if not self.logger:
self._init()
return self.logger
def _init(self):
# 创建 QueueHandler 对象,并设置日志级别和队列对象
logger = logging.getLogger(self.sign)
logger.setLevel(logging.INFO)
queue_handler = logging.handlers.QueueHandler(self.log_queue)
queue_handler.setLevel(logging.INFO)
logger.addHandler(queue_handler)
# 创建 FileHandler 对象,并设置日志级别和格式化方式
formatter = logging.Formatter(
'%(asctime)s - %(name)s - %(levelname)s - %(message)s')
if self.recode_file:
if self.mode == "T":
handler = TimedRotatingFileHandler(filename=self.filename,
encoding='UTF-8',
when="D",
interval=1,
backupCount=7
)
elif self.mode == "S":
handler = RotatingFileHandler(filename=self.filename,
encoding='UTF-8',
maxBytes=self.maxBytes,
backupCount=7
)
else:
raise ValueError("mode not support : {}".format(self.mode))
handler.setLevel(logging.INFO)
handler.setFormatter(formatter)
logger.addHandler(handler)
# 创建 StreamHandler 对象,并设置日志级别和格式化方式
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
self.logger = logger
return logger
问题记录:
from logging.handlers import TimedRotatingFileHandler
class MultiTimedRotatingFileHandler(TimedRotatingFileHandler):
"""
支持 多线程
"""
def doRollover(self) -> None:
if self.stream:
self.stream.close()
self.stream = None
# get the time that this sequence started at and make it a TimeTuple
currentTime = int(time.time())
dstNow = time.localtime(currentTime)[-1]
t = self.rolloverAt - self.interval
if self.utc:
timeTuple = time.gmtime(t)
else:
timeTuple = time.localtime(t)
dstThen = timeTuple[-1]
if dstNow != dstThen:
if dstNow:
addend = 3600
else:
addend = -3600
timeTuple = time.localtime(t + addend)
dfn = self.rotation_filename(self.baseFilename + "." +
time.strftime(self.suffix, timeTuple))
if os.path.exists(dfn):
os.remove(dfn)
# self.rotate(self.baseFilename, dfn)
single = False
while not single:
try:
self.rotate(self.baseFilename, dfn)
single = True
except:
pass
if self.backupCount > 0:
for s in self.getFilesToDelete():
os.remove(s)
if not self.delay:
self.stream = self._open()
newRolloverAt = self.computeRollover(currentTime)
while newRolloverAt <= currentTime:
newRolloverAt = newRolloverAt + self.interval
#If DST changes and midnight or weekly rollover, adjust for this.
if (self.when == 'MIDNIGHT' or self.when.startswith('W')) and not self.utc:
dstAtRollover = time.localtime(newRolloverAt)[-1]
if dstNow != dstAtRollover:
if not dstNow: # DST kicks in before next rollover, so we need to deduct an hour
addend = -3600
else: # DST bows out before next rollover, so we need to add an hour
addend = 3600
newRolloverAt += addend
self.rolloverAt = newRolloverAt