功能
可实现日志打印在控制台的同时,输出到文件中
且文件根据%Y%m%d或者%Y%m%d%H自动决定按天还是按小时分割
代码比较简单,比直接用自带的方便一些
代码
import sys
import traceback
import os as _os
import logging as _logging
import time as _time
import threading as _threading
_file_lock = _threading.RLock()
class DateRotatingFileHandler(_logging.StreamHandler):
"""
按天分片的LogHandler
"""
def __init__(self, file_path, surfix="%Y%m%d%H"):
"""
:param file_path: 日志路径(不含后缀)
:type file_path: str
:param surfix: 时间后缀, 可以使用python的dateformat参数. 默认为%Y%m%d%H
:type surfix: str
"""
_logging.StreamHandler.__init__(self)
self.stream = None
self._filePath = file_path
self._surfix = surfix
_file_lock.acquire()
try:
if _os.path.exists(self._filePath):
mtime = _os.stat(self._filePath).st_mtime
d_fmt = _time.strftime(self._surfix, _time.localtime(mtime))
self.stream = open(_os.path.join(self._filePath), "a")
self._currentSurfix = d_fmt
else:
self._currentSurfix = ""
finally:
_file_lock.release()
self.setFormatter(_logging.Formatter("%(asctime)s [%(levelname)s]\t%(message)s", "%Y-%m-%d %H:%M:%S"))
def _checkFile(self, ts):
d_fmt = _time.strftime(self._surfix, _time.localtime(ts))
if d_fmt != self._currentSurfix:
_file_lock.acquire()
try:
if not self.stream is None:
self.flush()
self.stream.close()
_os.rename(self._filePath, self._filePath + "." + self._currentSurfix)
self.stream = open(_os.path.join(self._filePath), "a")
self._currentSurfix = d_fmt
finally:
_file_lock.release()
def emit(self, record):
self._checkFile(record.created)
msg = self.format(record)
sys.stdout.write(msg+"\n")
sys.stdout.flush()
_logging.StreamHandler.emit(self, record)
def flush(self):
if self.stream and hasattr(self.stream, "flush") and not self.stream.closed:
_logging.StreamHandler.flush(self)
def writeRAW(self, line):
self._checkFile(_time.time())
self.stream.write(line)
self.stream.flush()
def close(self):
super(DateRotatingFileHandler, self).close()
if not self.stream is None:
try:
self.stream.close()
except:
traceback.print_exc()
h = DateRotatingFileHandler("./pg.log")
formatter = _logging.Formatter('\033[33m%(asctime)s - %(process)d - %(threadName)s - %(name)s - %(levelname)s - %(filename)s:%(lineno)d - %(funcName)s - %(message)s\033[0m')
h.setFormatter(formatter)
logger = _logging.getLogger("[TEST]")
logger.setLevel(_logging.DEBUG)
logger.handlers.clear()
logger.addHandler(h)
logger.info("tttttttttttt")
逻辑说明
- 生成pg.log文件
- 第二天的时候将pg.log重命名为 pg.log.%Y%m%d (%Y%m%d)
- 依次类推