python模块logging日志输出保存及解析

github源文件

1 日志保存与输出

1.0 测试用例

import logging
from logging import handlers
from flask import Flask

app = Flask(__name__)

class Logger(object):
    level_relations = {
        'debug':logging.DEBUG,
        'info':logging.INFO,
        'warning':logging.WARNING,
        'error':logging.ERROR,
        'crit':logging.CRITICAL
    }#日志级别关系映射

    def __init__(self,filename,level='info',when='D',backCount=3,fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'):
    	'''调用Logger类设定日志文件名称,以操作日志方法'''
        self.logger = logging.getLogger(filename)
        '''设置日志格式'''
        format_str = logging.Formatter(fmt)
        '''设置日志级别'''
        self.logger.setLevel(self.level_relations.get(level))
        '''屏幕输出日志信息'''
        sh = logging.StreamHandler()
        '''设置屏幕日志信息格式'''
        sh.setFormatter(format_str)
        '''指定间隔时间自动生成日志文件'''
        th = handlers.TimedRotatingFileHandler(filename=filename,when=when,backupCount=backCount,encoding='utf-8')
        '''设定写入文件的日志格式'''
        th.setFormatter(format_str)
        '''日志信息添加到Logger类变量hanlers列表中'''
        self.logger.addHandler(sh) 
        self.logger.addHandler(th)

@app.route("/save_log", methods=["POST"])
def save_log():
    log = Logger('all.log',level='debug')
    log.logger.debug('debug')
    log.logger.info('info')
    log.logger.warning('警告')
    log.logger.error('报错')
    log.logger.critical('严重')
    return "success"

if __name__ == '__main__':
    app.run(port=8090, debug=True)  

1.2 日志文件

all.log

2019-04-01 15:42:54,519 - log_save.py[line:37] - DEBUG: debug
2019-04-01 15:42:54,519 - log_save.py[line:38] - INFO: info
2019-04-01 15:42:54,520 - log_save.py[line:39] - WARNING: 警告
2019-04-01 15:42:54,520 - log_save.py[line:40] - ERROR: 报错
2019-04-01 15:42:54,520 - log_save.py[line:41] - CRITICAL: 严重

2 logging模块解析

2.1 初始化文件

__init__
getLogger函数:

def getLogger(name=None):
    """
    返回指定名称的logger,若未指定名称返回root.
    """
    if name:
        return Logger.manager.getLogger(name)
    else:
        return root
Logger.manager = Manager(Logger, root)
class Manager(object):
    """
    日志管理实例.
    """
    def __init__(self, rootnode):
        """
        初始化.
        """
        self.root = rootnode
        self.disable = 0
        self.emittedNoHandlerWarning = False
        self.loggerDict = {}
        self.loggerClass = None
        self.logRecordFactory = None

    def getLogger(self, name):
        """
        获取日志.
        """
        rv = None
        if not isinstance(name, str):
            raise TypeError('A logger name must be a string')
        _acquireLock()
        try:
            if name in self.loggerDict:
                rv = self.loggerDict[name]
                if isinstance(rv, PlaceHolder):
                    ph = rv
                    rv = (self.loggerClass or _loggerClass)(name)
                    rv.manager = self
                    self.loggerDict[name] = rv
                    self._fixupChildren(ph, rv)
                    self._fixupParents(rv)
            else:
                rv = (self.loggerClass or _loggerClass)(name)
                rv.manager = self
                self.loggerDict[name] = rv
                self._fixupParents(rv)
        finally:
            _releaseLock()
        return rv
_loggerClass = Logger

class Logger(Filterer):
    """
    日志级别控制.
    """
    def __init__(self, name, level=NOTSET):
        """
        初始化文件名和日志级别.
        """
        Filterer.__init__(self)
        self.name = name
        self.level = _checkLevel(level)
        self.parent = None
        self.propagate = True
        self.handlers = []
        self.disabled = False
        self._cache = {}

    def setLevel(self, level):
        """
        日志级别.
        """
        self.level = _checkLevel(level)
        self.manager._clear_cache()

    def debug(self, msg, *args, **kwargs):
        """
        debug级别.
        """
        if self.isEnabledFor(DEBUG):
            self._log(DEBUG, msg, args, **kwargs)

    def info(self, msg, *args, **kwargs):
        """
        info级别
        """
        if self.isEnabledFor(INFO):
            self._log(INFO, msg, args, **kwargs)

    def warning(self, msg, *args, **kwargs):
        """
        warning级别.
        """
        if self.isEnabledFor(WARNING):
            self._log(WARNING, msg, args, **kwargs)

    def warn(self, msg, *args, **kwargs):
        warnings.warn("The 'warn' method is deprecated, "
            "use 'warning' instead", DeprecationWarning, 2)
        self.warning(msg, *args, **kwargs)

    def error(self, msg, *args, **kwargs):
        """
        error级别.
        """
        if self.isEnabledFor(ERROR):
            self._log(ERROR, msg, args, **kwargs)

    def exception(self, msg, *args, exc_info=True, **kwargs):
        """
        用异常信息记录错误的方法.
        """
        self.error(msg, *args, exc_info=exc_info, **kwargs)

    def critical(self, msg, *args, **kwargs):
        """
        critical级别.
        """
        if self.isEnabledFor(CRITICAL):
            self._log(CRITICAL, msg, args, **kwargs)
	def addHandler(self, hdlr):
		_acquireLock()
		try:
			if not (hdlr in self.handlers):
				self.handlers.append(hdlr)
		finally:
			_releaseLock()

2.2 句柄文件

handlers.py

class TimedRotatingFileHandler(BaseRotatingHandler):
    """
    日志保存句柄:时间间隔操作日志.
    若 backupCount(备份文件数量) > 0, 回滚结束后,不再保存之前的文件,并删除最旧的文件.
    """
    def __init__(self, filename, when='h', interval=1, backupCount=0, encoding=None, delay=False, utc=False, atTime=None):
        BaseRotatingHandler.__init__(self, filename, 'a', encoding, delay)
        self.when = when.upper()
        self.backupCount = backupCount
        self.utc = utc
        self.atTime = atTime
        # 计算回滚时间.
        # S - 秒
        # M - 分
        # H - 时
        # D - 天
        # midnight - 午夜回滚
        # W{0-6} - 指定在星期几回滚; 0 - 星期一
        if self.when == 'S':
            self.interval = 1 # one second
            self.suffix = "%Y-%m-%d_%H-%M-%S"
            self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}(\.\w+)?$"
        elif self.when == 'M':
            self.interval = 60 # one minute
            self.suffix = "%Y-%m-%d_%H-%M"
            self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}-\d{2}(\.\w+)?$"
        elif self.when == 'H':
            self.interval = 60 * 60 # one hour
            self.suffix = "%Y-%m-%d_%H"
            self.extMatch = r"^\d{4}-\d{2}-\d{2}_\d{2}(\.\w+)?$"
        elif self.when == 'D' or self.when == 'MIDNIGHT':
            self.interval = 60 * 60 * 24 # one day
            self.suffix = "%Y-%m-%d"
            self.extMatch = r"^\d{4}-\d{2}-\d{2}(\.\w+)?$"
        elif self.when.startswith('W'):
            self.interval = 60 * 60 * 24 * 7 # one week
            if len(self.when) != 2:
                raise ValueError("You must specify a day for weekly rollover from 0 to 6 (0 is Monday): %s" % self.when)
            if self.when[1] < '0' or self.when[1] > '6':
                raise ValueError("Invalid day specified for weekly rollover: %s" % self.when)
            self.dayOfWeek = int(self.when[1])
            self.suffix = "%Y-%m-%d"
            self.extMatch = r"^\d{4}-\d{2}-\d{2}(\.\w+)?$"
        else:
            raise ValueError("Invalid rollover interval specified: %s" % self.when)

log_save.py

3 总结

日志记录流程:

Created with Raphaël 2.2.0 开始 日志文件操作类getLogger 日志级别setLevel 日志保存到文件TimedRotatingFileHandler 设置日志格式setFormatter 添加日志信息到文件addHandler 结束

[参考文献]
[1]https://github.com/python/cpython/blob/3.7/Lib/logging/init.py
[2]https://github.com/python/cpython/blob/3.7/Lib/logging/handlers.py


  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值