前段时间,我看到一个Mono应用程序的输出是彩色的,可能是因为它的日志系统(因为所有的消息都是标准化的)。
现在,Python有了日志记录模块,它允许您指定许多选项来定制输出。所以,我想象类似的事情可能与Python,但我不知道如何在任何地方做到这一点。
是否有办法使Python日志模块输出为彩色?
我想要的(例如)错误显示为红色,调试消息显示为蓝色或黄色,等等。
当然,这可能需要一个兼容的终端(大多数现代终端都是);但如果不支持颜色,我可以退回到原始的日志输出。
有什么想法,我可以得到彩色输出与日志模块?
import logging
import sys
colors = {'pink': '\033[95m', 'blue': '\033[94m', 'green': '\033[92m', 'yellow': '\033[93m', 'red': '\033[91m',
'ENDC': '\033[0m', 'bold': '\033[1m', 'underline': '\033[4m'}
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
def str_color(color, data):
return colors[color] + str(data) + colors['ENDC']
params = {'param1': id1, 'param2': id2}
logging.info('\nParams:' + str_color("blue", str(params)))`
您可以导入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')
输出:
另一个解决方案,用ZetaSyanthis的颜色:
def config_log(log_level):
def set_color(level, code):
level_fmt = "\033[1;" + str(code) + "m%s\033[1;0m"
logging.addLevelName( level, level_fmt % logging.getLevelName(level) )
std_stream = sys.stdout
isatty = getattr(std_stream, 'isatty', None)
if isatty and isatty():
levels = [logging.DEBUG, logging.CRITICAL, logging.WARNING, logging.ERROR]
for idx, level in enumerate(levels):
set_color(level, 30 + idx )
set_color(logging.DEBUG, 0)
logging.basicConfig(stream=std_stream, level=log_level)
在__main__函数中调用它一次。我这里有这样的东西:
options, arguments = p.parse_args()
log_level = logging.DEBUG if options.verbose else logging.WARNING
config_log(log_level)
它还验证输出是否为控制台,否则不使用颜色。
如果有人正在寻找一个漂亮的着色以及自定义日志级别着色,你可以看看这个改编的解决方案(它使用moecololelibrary):
#Install moecolor
pip install moecolor
from moecolor import FormatText as ft
class ConsoleFormatter(logging.Formatter):
default_format = f"[%(asctime)s | %(name)s | %(funcName)s | LN%(lineno)s | %(levelname)s]: %(message)s"
time_portion = ft('%(asctime)s', color='purple').text
format_portion = ' | %(name)s | %(funcName)s | LN%(lineno)d | %(levelname)s]: '
FORMATS = {
'DEBUG': time_portion + ft(format_portion, color='yellow').text + ft('%(message)s', color='fff9ae').text,
'INFO': time_portion + ft(format_portion, color='green').text + ft('%(message)s', color='#d3ffb3').text,
'WARNING': time_portion + ft(format_portion, color='orange').text + ft('%(message)s', color='#ffc100').text,
'TIMER': time_portion + ft(format_portion, color='blue').text + ft('%(message)s', color='#00b4d8').text, # Note, this is a custom log level
'ERROR': time_portion + ft(format_portion, color='red').text + ft('%(message)s', color='#ba262b').text,
'CRITICAL': time_portion + ft(format_portion, color='#8D0101').text + ft('%(message)s', color='#D5212E').text,
}
def format(self, record):
_format = self.FORMATS.get(record.levelname, self.default_format)
formatter = logging.Formatter(_format)
return formatter.format(record)
你可以这样使用它:
console_handler = logging.StreamHandler()
console_handler.setFormatter(ConsoleFormatter())
使用龙卷风库
Tornado web框架提供了一些实用程序,包括Tornado .log. logformatter格式化程序,它可以在没有框架其他部分的情况下使用。
对不支持ANSI颜色代码的Windows版本的颜色支持是通过使用colorama库启用的。希望使用它的应用程序必须首先调用colorama.init来初始化colorama。
import logging
import tornado.log
# import colorama # uncomment on some Windows versions
# colorama.init()
consoleHandler = logging.StreamHandler()
consoleHandler.setFormatter(tornado.log.LogFormatter())
logging.basicConfig(level=logging.DEBUG, handlers=[consoleHandler])
logger = logging.getLogger("test")
logger.info("hello world")