前段时间,我看到一个Mono应用程序的输出是彩色的,可能是因为它的日志系统(因为所有的消息都是标准化的)。
现在,Python有了日志记录模块,它允许您指定许多选项来定制输出。所以,我想象类似的事情可能与Python,但我不知道如何在任何地方做到这一点。
是否有办法使Python日志模块输出为彩色?
我想要的(例如)错误显示为红色,调试消息显示为蓝色或黄色,等等。
当然,这可能需要一个兼容的终端(大多数现代终端都是);但如果不支持颜色,我可以退回到原始的日志输出。
有什么想法,我可以得到彩色输出与日志模块?
我更喜欢使用这个片段:
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")
下面的解决方案只适用于python 3,但对我来说,它看起来是最清楚的。
其思想是使用日志记录工厂向日志记录对象添加“有色”属性,然后在日志格式中使用这些“有色”属性。
import logging
logger = logging.getLogger(__name__)
def configure_logging(level):
# add 'levelname_c' attribute to log resords
orig_record_factory = logging.getLogRecordFactory()
log_colors = {
logging.DEBUG: "\033[1;34m", # blue
logging.INFO: "\033[1;32m", # green
logging.WARNING: "\033[1;35m", # magenta
logging.ERROR: "\033[1;31m", # red
logging.CRITICAL: "\033[1;41m", # red reverted
}
def record_factory(*args, **kwargs):
record = orig_record_factory(*args, **kwargs)
record.levelname_c = "{}{}{}".format(
log_colors[record.levelno], record.levelname, "\033[0m")
return record
logging.setLogRecordFactory(record_factory)
# now each log record object would contain 'levelname_c' attribute
# and you can use this attribute when configuring logging using your favorite
# method.
# for demo purposes I configure stderr log right here
formatter_c = logging.Formatter("[%(asctime)s] %(levelname_c)s:%(name)s:%(message)s")
stderr_handler = logging.StreamHandler()
stderr_handler.setLevel(level)
stderr_handler.setFormatter(formatter_c)
root_logger = logging.getLogger('')
root_logger.setLevel(logging.DEBUG)
root_logger.addHandler(stderr_handler)
def main():
configure_logging(logging.DEBUG)
logger.debug("debug message")
logger.info("info message")
logger.critical("something unusual happened")
if __name__ == '__main__':
main()
您可以轻松地修改此示例,以创建其他彩色属性(f.e. message_c),然后使用这些属性(仅)在需要的位置获取彩色文本。
(我最近发现的一个方便的技巧:我有一个带有彩色调试日志的文件,每当我想临时增加我的应用程序的日志级别时,我只需在不同的终端中跟踪-f日志文件,并在屏幕上看到调试日志,w/o更改任何配置并重新启动应用程序)