前段时间,我看到一个Mono应用程序的输出是彩色的,可能是因为它的日志系统(因为所有的消息都是标准化的)。
现在,Python有了日志记录模块,它允许您指定许多选项来定制输出。所以,我想象类似的事情可能与Python,但我不知道如何在任何地方做到这一点。
是否有办法使Python日志模块输出为彩色?
我想要的(例如)错误显示为红色,调试消息显示为蓝色或黄色,等等。
当然,这可能需要一个兼容的终端(大多数现代终端都是);但如果不支持颜色,我可以退回到原始的日志输出。
有什么想法,我可以得到彩色输出与日志模块?
我已经创建了一个类,它将用您选择的任何颜色显示错误级别名称。大部分代码只是定义颜色模式,然后覆盖对象中的一些变量供日志库使用
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")
另一个解决方案,用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)
它还验证输出是否为控制台,否则不使用颜色。
coloredlogs
Instalation
pip install coloredlogs
使用
最小的用法:
import logging
import coloredlogs
coloredlogs.install() # install a handler on the root logger
logging.debug('message with level debug')
logging.info('message with level info')
logging.warning('message with level warning')
logging.error('message with level error')
logging.critical('message with level critical')
结果:
从消息级调试开始:
import logging
import coloredlogs
coloredlogs.install(level='DEBUG') # install a handler on the root logger with level debug
logging.debug('message with level debug')
logging.info('message with level info')
logging.warning('message with level warning')
logging.error('message with level error')
logging.critical('message with level critical')
结果:
从库中隐藏消息:
import logging
import coloredlogs
logger = logging.getLogger(__name__) # get a specific logger object
coloredlogs.install(level='DEBUG') # install a handler on the root logger with level debug
coloredlogs.install(level='DEBUG', logger=logger) # pass a specific logger object
logging.debug('message with level debug')
logging.info('message with level info')
logging.warning('message with level warning')
logging.error('message with level error')
logging.critical('message with level critical')
结果:
格式化日志消息:
import logging
import coloredlogs
logger = logging.getLogger(__name__) # get a specific logger object
coloredlogs.install(level='DEBUG') # install a handler on the root logger with level debug
coloredlogs.install(level='DEBUG', logger=logger) # pass a specific logger object
coloredlogs.install(
level='DEBUG', logger=logger,
fmt='%(asctime)s.%(msecs)03d %(filename)s:%(lineno)d %(levelname)s %(message)s'
)
logging.debug('message with level debug')
logging.info('message with level info')
logging.warning('message with level warning')
logging.error('message with level error')
logging.critical('message with level critical')
结果:
可用的格式属性:
%(asctime)s - Time as human-readable string, when logging call was issued
%(created)f - Time as float when logging call was issued
%(filename)s - File name
%(funcName)s - Name of function containing the logging call
%(hostname)s - System hostname
%(levelname)s - Text logging level
%(levelno)s - Integer logging level
%(lineno)d - Line number where the logging call was issued
%(message)s - Message passed to logging call (same as %(msg)s)
%(module)s - File name without extension where the logging call was issued
%(msecs)d - Millisecond part of the time when logging call was issued
%(msg)s - Message passed to logging call (same as %(message)s)
%(name)s - Logger name
%(pathname)s - Full pathname to file containing the logging call
%(process)d - Process ID
%(processName)s - Process name
%(programname)s - System programname
%(relativeCreated)d - Time as integer in milliseconds when logging call was issued, relative to the time when logging module was loaded
%(thread)d - Thread ID
%(threadName)s - Thread name
%(username)s - System username
来源:
Coloredlogs包
日志库
这是@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]
)
现在有一个发布的PyPi模块,用于自定义彩色日志输出:
https://pypi.python.org/pypi/rainbow_logging_handler/
and
https://github.com/laysakura/rainbow_logging_handler
支持Windows
支持Django
可定制的颜色
由于它是作为Python卵分发的,因此非常容易为任何Python应用程序安装它。