前段时间,我看到一个Mono应用程序的输出是彩色的,可能是因为它的日志系统(因为所有的消息都是标准化的)。
现在,Python有了日志记录模块,它允许您指定许多选项来定制输出。所以,我想象类似的事情可能与Python,但我不知道如何在任何地方做到这一点。
是否有办法使Python日志模块输出为彩色?
我想要的(例如)错误显示为红色,调试消息显示为蓝色或黄色,等等。
当然,这可能需要一个兼容的终端(大多数现代终端都是);但如果不支持颜色,我可以退回到原始的日志输出。
有什么想法,我可以得到彩色输出与日志模块?
安装colorlog包,你可以立即在你的日志消息中使用颜色:
获取一个记录器实例,就像您通常所做的那样。
设置日志级别。您也可以使用像DEBUG这样的常量
和INFO从日志模块直接。
将消息格式化程序设置为所提供的ColoredFormatter
通过colorlog库。
import colorlog
logger = colorlog.getLogger()
logger.setLevel(colorlog.colorlog.logging.DEBUG)
handler = colorlog.StreamHandler()
handler.setFormatter(colorlog.ColoredFormatter())
logger.addHandler(handler)
logger.debug("Debug message")
logger.info("Information message")
logger.warning("Warning message")
logger.error("Error message")
logger.critical("Critical message")
输出:
更新:额外信息
只需更新ColoredFormatter:
handler.setFormatter(colorlog.ColoredFormatter('%(log_color)s [%(asctime)s] %(levelname)s [%(filename)s.%(funcName)s:%(lineno)d] %(message)s', datefmt='%a, %d %b %Y %H:%M:%S'))
输出:
包:
pip install colorlog
输出:
Collecting colorlog
Downloading colorlog-4.6.2-py2.py3-none-any.whl (10.0 kB)
Installing collected packages: colorlog
Successfully installed colorlog-4.6.2
虽然其他解决方案看起来不错,但它们存在一些问题。有些人会给整条线上色,有时这是不需要的,有些人会省略你可能在一起的任何配置。下面的解决方案只影响消息本身。
Code
class ColoredFormatter(logging.Formatter):
def format(self, record):
if record.levelno == logging.WARNING:
record.msg = '\033[93m%s\033[0m' % record.msg
elif record.levelno == logging.ERROR:
record.msg = '\033[91m%s\033[0m' % record.msg
return logging.Formatter.format(self, record)
例子
logger = logging.getLogger('mylogger')
handler = logging.StreamHandler()
log_format = '[%(asctime)s]:%(levelname)-7s:%(message)s'
time_format = '%H:%M:%S'
formatter = ColoredFormatter(log_format, datefmt=time_format)
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.warn('this should be yellow')
logger.error('this should be red')
输出
[17:01:36]:WARNING:this should be yellow
[17:01:37]:ERROR :this should be red
如您所见,其他所有内容仍然输出并保持初始颜色。如果您想要更改消息以外的任何内容,您可以简单地将颜色代码传递给示例中的log_format。
这是@Sergey Pleshakov的出色回答的轻微变化,他只对关卡使用颜色,并像预期的那样使用basicConfig:
class CustomFormatter(logging.Formatter):
white = "\x1b[97;20m"
grey = "\x1b[38;20m"
green = "\x1b[32;20m"
cyan = "\x1b[36;20m"
yellow = "\x1b[33;20m"
red = "\x1b[31;20m"
bold_red = "\x1b[31;1m"
reset = "\x1b[0m"
fmt = "%(asctime)s - {}%(levelname)-8s{} - %(name)s.%(funcName)s - %(message)s"
FORMATS = {
logging.DEBUG: fmt.format(grey, reset),
logging.INFO: fmt.format(green, reset),
logging.WARNING: fmt.format(yellow, reset),
logging.ERROR: fmt.format(red, reset),
logging.CRITICAL: fmt.format(bold_red, reset),
}
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt, datefmt="%H:%M:%S")
return formatter.format(record)
handler = logging.StreamHandler()
handler.setFormatter(CustomFormatter())
logging.basicConfig(
level=logging.DEBUG,
handlers=[handler]
)
我更喜欢使用这个片段:
import logging
from enum import Enum
CSI = '\033['
Color = Enum(
'Color', 'BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE', start=30
)
class AnsiColorHandler(logging.StreamHandler):
LOGLEVEL_COLORS = {
'DEBUG': Color.BLUE,
'INFO': Color.GREEN,
'WARNING': Color.RED,
'ERROR': Color.RED,
'CRITICAL': Color.RED,
}
def __init__(self) -> None:
super().__init__()
self.formatter = logging.Formatter("%(levelname)-8s - %(message)s")
def format(self, record: logging.LogRecord) -> str:
message: str = super().format(record)
# use colors in tty
if self.stream.isatty() and (
color := self.LOGLEVEL_COLORS.get(record.levelname)
):
message = f'{CSI}{color.value}m{message}{CSI}0m'
return message
# setup logger
# logger = logging.getLogger(__package__)
logger = logging.getLogger(__name__)
logger.addHandler(AnsiColorHandler())
用法:
import logging
from .log import logger
logger.setLevel(logging.DEBUG)
logger.debug("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
我遇到的麻烦是正确设置格式化程序:
class ColouredFormatter(logging.Formatter):
def __init__(self, msg):
logging.Formatter.__init__(self, msg)
self._init_colour = _get_colour()
def close(self):
# restore the colour information to what it was
_set_colour(self._init_colour)
def format(self, record):
# Add your own colourer based on the other examples
_set_colour( LOG_LEVEL_COLOUR[record.levelno] )
return logging.Formatter.format(self, record)
def init():
# Set up the formatter. Needs to be first thing done.
rootLogger = logging.getLogger()
hdlr = logging.StreamHandler()
fmt = ColouredFormatter('%(message)s')
hdlr.setFormatter(fmt)
rootLogger.addHandler(hdlr)
然后使用:
import coloured_log
import logging
coloured_log.init()
logging.info("info")
logging.debug("debug")
coloured_log.close() # restore colours