logging 开启日志颜色的完美方式

我们都知道python自带的logging模块只能记录普通的白色,这样看起来控制台显得有点杂乱无章。有没有方法改变输出等级的颜色呢?这样的信息检索起来效率更高点。

当然是有的,而且利用logging自带的特性就能完成。

原理

我们这里主要是利用logging的Filter类,此类可以控制是否输出日志,同时修改日志的上下文环境。

先来看下面的代码:

import logging
from random import randint

class MyFilter(logging.Filter):

    def filter(self, record: logging.LogRecord) -> bool:
        # 当有新日志需要被记录时,此函数会被调用,用于判断是否记录该日志
        # 返回True代表允许记录,False代表不允许记录。
        record.rand = randint(0, 1024) # 此处修改上下文环境。
        return True

fmter = logging.Formatter("%(name)s - %(levelname)s - rand:%(rand)s - %(message)s")
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(fmter)
ch.addFilter(MyFilter())

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.addHandler(ch)


logger.info('test info')
logger.error('test error')

本段代码的功能就是在 Filter 中修改这个 record,也就是修改了记录时的上下文环境。

看到这一行

fmter = logging.Formatter("%(name)s - %(levelname)s - rand:%(rand)s - %(message)s")

注意到了吗,我们这里引用了 rand:%(rand)s ,这个 rand 在 MyFilter 中被定义,handler 在输出时是如何找到 fmter 所定义的变量的呢? 其实就是去上下文里找,然鹅这个上下文被链接到了 record 中,所以你修改了 record 也就是修改了上下文环境。

如果你看懂了,就会灵光乍现

既然 fmter 定义的变量都是去 record 里面找的,那我们直接修改 levelname 变量,让他根据相应的等级输出对应的颜色不就好了吗?

没错,是这样的!

封装参考

# colorlogging.py

import logging

# 此处修改颜色
FMTDCIT = {
    'ERROR'   : "\033[31mERROR\033[0m",
    'INFO'    : "\033[37mINFO\033[0m",
    'DEBUG'   : "\033[1mDEBUG\033[0m",
    'WARN'    : "\033[33mWARN\033[0m",
    'WARNING' : "\033[33mWARNING\033[0m",
    'CRITICAL': "\033[35mCRITICAL\033[0m",
}

class Filter(logging.Filter):
    def __init__(self, **kwargs) -> None:
        super().__init__(**kwargs)

    def filter(self, record: logging.LogRecord) -> bool:
        record.levelname = FMTDCIT.get(record.levelname)
        return True

filter = Filter()

def getLogger(
    name: str, 
    level: int    = logging.INFO,
    fmt: str      = "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    fmt_date: str = "%H:%M:%S"
    ) -> logging.Logger:
    
    
    fmter = logging.Formatter(fmt, fmt_date)
    ch = logging.StreamHandler()
    ch.setLevel(level)
    ch.setFormatter(fmter)
    ch.addFilter(filter)

    logger = logging.getLogger(name)
    logger.setLevel(level)
    logger.addHandler(ch)
    return logger

可以参考我的代码直接封装成一个模块使用,可以根据自己的需要进行自定义,下面看调用的例子:

import colorlogging
import logging

logger = colorlogging.getLogger(__name__, logging.DEBUG)

logger.debug("DEBUG")
logger.info("INFO")
logger.warning("WARN")
logger.error("ERROR")
logger.critical("CRITICAL")

效果:

留下评论