前段时间,我看到一个Mono应用程序的输出是彩色的,可能是因为它的日志系统(因为所有的消息都是标准化的)。
现在,Python有了日志记录模块,它允许您指定许多选项来定制输出。所以,我想象类似的事情可能与Python,但我不知道如何在任何地方做到这一点。
是否有办法使Python日志模块输出为彩色?
我想要的(例如)错误显示为红色,调试消息显示为蓝色或黄色,等等。
当然,这可能需要一个兼容的终端(大多数现代终端都是);但如果不支持颜色,我可以退回到原始的日志输出。
有什么想法,我可以得到彩色输出与日志模块?
我修改了Sorin提供的原始示例,并将StreamHandler子类化为ColorizedConsoleHandler。
他们的解决方案的缺点是它修改了消息,并且因为修改了实际的日志消息,任何其他处理程序也将得到修改后的消息。
在我们的例子中,这导致日志文件中有颜色代码,因为我们使用了多个记录器。
下面的类只在支持ANSI的平台上工作,但是向它添加Windows颜色代码应该很简单。
import copy
import logging
class ColoredConsoleHandler(logging.StreamHandler):
def emit(self, record):
# Need to make a actual copy of the record
# to prevent altering the message for other loggers
myrecord = copy.copy(record)
levelno = myrecord.levelno
if(levelno >= 50): # CRITICAL / FATAL
color = '\x1b[31m' # red
elif(levelno >= 40): # ERROR
color = '\x1b[31m' # red
elif(levelno >= 30): # WARNING
color = '\x1b[33m' # yellow
elif(levelno >= 20): # INFO
color = '\x1b[32m' # green
elif(levelno >= 10): # DEBUG
color = '\x1b[35m' # pink
else: # NOTSET and anything else
color = '\x1b[0m' # normal
myrecord.msg = color + str(myrecord.msg) + '\x1b[0m' # normal
logging.StreamHandler.emit(self, myrecord)
import logging
logging.basicConfig(filename="f.log" filemode='w', level=logging.INFO,
format = "%(logger_name)s %(color)s %(message)s %(endColor)s")
class Logger(object):
__GREEN = "\033[92m"
__RED = '\033[91m'
__ENDC = '\033[0m'
def __init__(self, name):
self.logger = logging.getLogger(name)
self.extra={'logger_name': name, 'endColor': self.__ENDC, 'color': self.__GREEN}
def info(self, msg):
self.extra['color'] = self.__GREEN
self.logger.info(msg, extra=self.extra)
def error(self, msg):
self.extra['color'] = self.__RED
self.logger.error(msg, extra=self.extra)
使用
日志记录器("文件名").info("显示绿色文本")
我已经创建了一个类,它将用您选择的任何颜色显示错误级别名称。大部分代码只是定义颜色模式,然后覆盖对象中的一些变量供日志库使用
class ColorLognameFormatter(logging.Formatter):
_level_str_len = 8
# Define the color codes
_reset_str = '\x1b[0m'
_grey_str = '\x1b[38;21m'
_blue_str = '\x1b[38;5;39m'
_yllw_str = '\x1b[38;5;226m'
_sred_str = '\x1b[38;5;196m'
_bred_str = '\x1b[31;1m'
# Make the basic strings
_debug_color_str = f"{_grey_str}DEBUG{_reset_str}".ljust(_level_str_len + len(_reset_str) + len(_grey_str), ' ')
_info_color_str = f"{_blue_str}INFO{_reset_str}".ljust(_level_str_len + len(_reset_str) + len(_blue_str), ' ')
_warn_color_str = f"{_yllw_str}WARNING{_reset_str}".ljust(_level_str_len + len(_reset_str) + len(_yllw_str), ' ')
_error_color_str = f"{_sred_str}ERROR{_reset_str}".ljust(_level_str_len + len(_reset_str) + len(_sred_str), ' ')
_crit_color_str = f"{_bred_str}CRITICAL{_reset_str}".ljust(_level_str_len + len(_reset_str) + len(_bred_str), ' ')
# Format into a dict
_color_levelname = {'DEBUG': _debug_color_str,
'INFO': _info_color_str,
'WARNING': _warn_color_str,
'ERROR': _error_color_str,
'CRITICAL': _error_color_str}
def __init__(self, fmt='%(levelname)s | %(message)s', *args, **kwargs):
super().__init__(fmt, *args, **kwargs)
def format(self, record):
# When calling format, replace the levelname with a colored version
# Note: the string size is greatly increased because of the color codes
record.levelname = self._color_levelname[record.levelname]
return super().format(record)
主要的变化是它将默认的fmt字符串设置为%(levelname)s | %(message)s,并在调用format之前替换levelname
用法:
from ColorLognameFormatter import ColorLognameFormatter
import logging
log_level = logging.INFO
logger = logging.getLogger(__name__)
logger.setLevel(log_level)
stdout_handler = logging.StreamHandler()
stdout_handler.setLevel(log_level)
stdout_handler.setFormatter(ColorLognameFormatter())
logger.addHandler(stdout_handler)
logger.propagate = False
logger.info("Test")
您可以导入colorlog模块,并使用它的ColoredFormatter对日志消息进行着色。
例子
主模块样板:
import logging
import os
import sys
try:
import colorlog
except ImportError:
pass
def setup_logging():
root = logging.getLogger()
root.setLevel(logging.DEBUG)
format = '%(asctime)s - %(levelname)-8s - %(message)s'
date_format = '%Y-%m-%d %H:%M:%S'
if 'colorlog' in sys.modules and os.isatty(2):
cformat = '%(log_color)s' + format
f = colorlog.ColoredFormatter(cformat, date_format,
log_colors = { 'DEBUG' : 'reset', 'INFO' : 'reset',
'WARNING' : 'bold_yellow', 'ERROR': 'bold_red',
'CRITICAL': 'bold_red' })
else:
f = logging.Formatter(format, date_format)
ch = logging.StreamHandler()
ch.setFormatter(f)
root.addHandler(ch)
setup_logging()
log = logging.getLogger(__name__)
该代码仅在安装了colorlog模块并且输出实际发送到终端时才启用日志消息中的颜色。这可以避免在日志输出重定向时将转义序列写入文件。
此外,还设置了一个自定义配色方案,更适合具有深色背景的终端。
一些日志调用示例:
log.debug ('Hello Debug')
log.info ('Hello Info')
log.warn ('Hello Warn')
log.error ('Hello Error')
log.critical('Hello Critical')
输出: