Python logging config (看这篇就够了)

  1. 复制粘贴直接用,以下文字可以不看。
  2. 是有颜色的日志哦,在输出到 console时。颜色定义在log_colors_config属性里,诸君可以修改为自己喜欢的颜色。
  3. BASE_PATH是项目根路径。
  4. init_handlers方法定义了对象logs_handler_paths,这个对象会在日志器初始化时,告诉日志器某个日志级别要使用哪个Handler,比如在这里info debug 和 notset这三个日志级别都使用的TimedRotatingFileHandlerwarning error 和 exception这三个日志级别则使用的RotatingFileHandler。你可以在logs_handler_paths对象里进行新增或修改,从而把某个日志级别修改为你想用的Handler
  5. Handler初始化的参数也定义在init_handlers方法,参数都存储在log_handler_params对象里。关于Handler都可以使用哪些参数和参数意义这里就不加赘述了,诸君可以搜索其它教程。
  6. 为诸君阐述下这里定义的两个Handler使用的参数意义:TimedRotatingFileHandler定义了info debug 和 notset 会在每天凌晨生成一个新的日志文件;当天的日志都会记录到新的文件里;backupCount表示了只会存储十个这样的文件(超过十个的话旧的就会被删除)。RotatingFileHandler定义了warning error 和 exception的日志文件大小达到1M以后, 会自动再创建文件记录,backupCount表示只会存储十个这样大小的文件。
  7. 日志过滤方法定义在should_log函数里了,这里把console使用过滤的示例给注释了,各位按需自取。
  8. [白白勿看]这里使用Message方法自己组织了输出格式,是因为在其它文件调用logger初始化日志器后,在使用info等方法输出日志时,实际上的输出文件名是logger.py自身,所以在Formatter输出filename时并不能够输出正确的调用文件名。

白白要知道日志级别哦: debug < info < warning < error < critical

诸君新建一个logger.py文件,代码复制粘贴,直接调用即可。不要忘记给赞b( ̄▽ ̄)d~

import inspect
import logging
import os
from logging.handlers import RotatingFileHandler, TimedRotatingFileHandler

import colorlog

try:
    from config import BASE_PATH
except:
    BASE_PATH = os.path.dirname(os.path.abspath(__file__))

LOG_PATH = os.path.join(BASE_PATH, "logs")


def message(func):
    def wrapper(_self, message):
        frame, filename, lineNo, functionName, code, unknowField = inspect.stack()[
            1]
        filename = os.path.basename(filename)
        message = "[{}:{}] [{}] - {}".format(filename,
                                             lineNo, functionName, message)
        func(_self, message)
    return wrapper


class Log(object):
    def __init__(self):
        self.info_log_path = os.path.join(LOG_PATH, "info")
        self.debug_log_path = os.path.join(LOG_PATH, "debug")
        self.warning_log_path = os.path.join(LOG_PATH, "warning")
        self.error_log_path = os.path.join(LOG_PATH, "error")
        self.critical_log_path = os.path.join(LOG_PATH, "critical")
        self.notset_log_path = os.path.join(LOG_PATH, "notset")
        self.log_dir_check()

        self.logs_handlers = None
        self.init_handlers()

        self.__loggers = dict()
        self.log_colors_config = {
            'DEBUG': 'cyan',
            'INFO': 'green',
            'WARNING': 'yellow',
            'ERROR': 'red',
            'CRITICAL': 'red',
            'NOTSET': 'red'
        }
        self.init_loggers()

    def log_dir_check(self):
        if not os.path.exists(LOG_PATH):
            os.makedirs(LOG_PATH)
        for path in [self.info_log_path, self.error_log_path, self.debug_log_path, self.warning_log_path, self.error_log_path, self.critical_log_path, self.notset_log_path]:
            if not os.path.exists(path):
                os.makedirs(path)

    def init_handlers(self):
        logs_handler_paths = {
            RotatingFileHandler: {
                logging.WARNING: os.path.join(self.warning_log_path, 'warning.log'),
                logging.ERROR: os.path.join(self.error_log_path, 'error.log'),
                logging.CRITICAL: os.path.join(self.critical_log_path, 'critical.log'),
            },
            TimedRotatingFileHandler: {
                logging.NOTSET: os.path.join(self.notset_log_path, 'notset.log'),
                logging.DEBUG: os.path.join(self.debug_log_path, 'debug.log'),
                logging.INFO: os.path.join(self.info_log_path, 'info.log'),
            }
        }
        log_handler_params = {
            TimedRotatingFileHandler: dict(when='midnight', interval=1, backupCount=10, encoding="utf-8"),
            RotatingFileHandler: dict(
                maxBytes=1024 * 1024, backupCount=10, encoding="utf-8")
        }
        self.logs_handlers = {log_level: log_handler(
            log_path, **log_handler_params[log_handler]) for log_handler, log_level_paths in logs_handler_paths.items() for log_level, log_path in log_level_paths.items()}

    def init_loggers(self):
        def should_log(record):
            """
            定义日志过滤规则
            :param record: 日志信息,拥有日志的自有属性,如 lineno
            :return: True or False
            """
            if record.levelname not in ["INFO", "WARNING", "DEBUG"]:
                return False
            return True

        _ = '%(log_color)s[%(asctime)s] [%(levelname)s] %(message)s'
        formatter = colorlog.ColoredFormatter(
            _, log_colors=self.log_colors_config)

        for log_level, log_handler in self.logs_handlers.items():
            logger = logging.getLogger(str(log_level))

            logger.propagate = False  # 阻止向 root 传播,True会导致console两次
            logger.setLevel(log_level)
            # 一些 handler
            log_handler = log_handler
            console = logging.StreamHandler()

            # 为刚创建的日志记录器设置日志记录格式
            log_handler.setFormatter(formatter)
            console.setFormatter(formatter)

            # 对日志器等级进行配置
            console.setLevel(log_level)
            log_handler.setLevel(log_level)

            # 初始化日志过滤器,并添加至 console
            # logging_filter = logging.Filter()
            # logging_filter.filter = should_log
            # console.addFilter(logging_filter)

            # 设置 TimedRotatingFileHandler 后缀名称,跟 strftime 的格式一样
            if TimedRotatingFileHandler == type(log_handler):
                log_handler.suffix = "%Y-%m-%d_%H-%M-%S.log"

            # 为日志工具对象添加日志记录器
            logger.addHandler(console)
            logger.addHandler(log_handler)

            self.__loggers.update({log_level: logger})

    @message
    def info(self, message):
        self.__loggers[logging.INFO].info(message)

    @message
    def error(self, message):
        self.__loggers[logging.ERROR].error(message)

    @message
    def exception(self, message):
        self.__loggers[logging.ERROR].exception(message)

    @message
    def warning(self, message):
        self.__loggers[logging.WARNING].warning(message)

    @message
    def debug(self, message):
        self.__loggers[logging.DEBUG].debug(message)

    @message
    def critical(self, message):
        self.__loggers[logging.CRITICAL].critical(message)


logger = Log()

if __name__ == "__main__":
    logger.info("info")
    logger.error("error")
    logger.debug("debug")
    try:
        a = 0/0
    except Exception as e:
        logger.exception(e)
    logger.warning("warning")
    logger.critical("critical")

白白示例:

from logger import logger
logger.info("info")
logger.error("error")
logger.debug("debug")
logger.warning("debug")
  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泡泡码客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值