我们都知道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")
效果:
