Python logging模塊在多進程下不保證同步,所以 TimedRotating 的情況下可能會導致某些日誌文件丟失,下面是一種簡單的解決辦法,對於日誌完整行要求不是很嚴格的情況下可以使用。
# coding:utf-8
import time
import os
import logging
from logging.handlers import TimedRotatingFileHandler
from .config import config
def init_logger(fname, logger_name):
log_file = config.get("log", "LOG_PATH") + fname
logger = logging.getLogger(logger_name)
# level = config.get('log', 'log_level')
logger.setLevel(logging.INFO)
fmt = "%(asctime)s %(filename)s %(lineno)d %(levelname)s %(message)s"
handler = MultiprocessTimedRotatingFileHandler(log_file, "midnight", 1, 7)
handler.setFormatter(logging.Formatter(fmt))
logger.addHandler(handler)
return logger
class MultiprocessTimedRotatingFileHandler(TimedRotatingFileHandler):
def __init__(self, filename, when="h", interval=1, backupCount=0,
encoding=None, delay=False, utc=False):
TimedRotatingFileHandler.__init__(self, filename, when=when,
interval=interval,
backupCount=backupCount,
encoding=encoding, delay=delay,
utc=utc)
def computeRollover(self, currentTime):
t_str = time.strftime(self.suffix, time.localtime(currentTime))
t = time.mktime(time.strptime(t_str, self.suffix))
return TimedRotatingFileHandler.computeRollover(self, t)
def doRollover(self):
if self.stream:
self.stream.close()
self.stream = None
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.baseFilename + "." + time.strftime(self.suffix, timeTuple)
if not os.path.exists(dfn):
try:
os.rename(self.baseFilename, dfn)
except OSError:
pass
if self.backupCount > 0:
for s in self.getFilesToDelete():
try:
os.remove(s)
except OSError:
pass
if hasattr(self, 'delay') and 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