air*_*ind 326 python logging colors
前段时间,我看到一个带有彩色输出的Mono应用程序,可能是因为它的日志系统(因为所有的消息都是标准化的).
现在,Python有了这个logging
模块,它允许你指定很多选项来自定义输出.所以,我想象Python可能会有类似的东西,但我无法在任何地方找到如何做到这一点.
有没有办法让Python logging
模块输出颜色?
我想要的(例如)红色错误,蓝色或黄色调试消息,等等.
当然这可能需要一个兼容的终端(大多数现代终端); 但logging
如果不支持颜色,我可以回退到原始输出.
有关如何使用记录模块获得彩色输出的任何想法?
air*_*ind 183
我已经知道了颜色逃逸,我刚才在我的bash提示中使用过它们.不管怎么说,还是要谢谢你.
我想要的是将它与日志记录模块集成,我最终在经过几次尝试和错误之后做了.
这是我最终得到的:
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
#The background is set with 40 plus the number of the color, and the foreground with 30
#These are the sequences need to get colored ouput
RESET_SEQ = "\033[0m"
COLOR_SEQ = "\033[1;%dm"
BOLD_SEQ = "\033[1m"
def formatter_message(message, use_color = True):
if use_color:
message = message.replace("$RESET", RESET_SEQ).replace("$BOLD", BOLD_SEQ)
else:
message = message.replace("$RESET", "").replace("$BOLD", "")
return message
COLORS = {
'WARNING': YELLOW,
'INFO': WHITE,
'DEBUG': BLUE,
'CRITICAL': YELLOW,
'ERROR': RED
}
class ColoredFormatter(logging.Formatter):
def __init__(self, msg, use_color = True):
logging.Formatter.__init__(self, msg)
self.use_color = use_color
def format(self, record):
levelname = record.levelname
if self.use_color and levelname in COLORS:
levelname_color = COLOR_SEQ % (30 + COLORS[levelname]) + levelname + RESET_SEQ
record.levelname = levelname_color
return logging.Formatter.format(self, record)
Run Code Online (Sandbox Code Playgroud)
要使用它,请创建自己的Logger:
# Custom logger class with multiple destinations
class ColoredLogger(logging.Logger):
FORMAT = "[$BOLD%(name)-20s$RESET][%(levelname)-18s] %(message)s ($BOLD%(filename)s$RESET:%(lineno)d)"
COLOR_FORMAT = formatter_message(FORMAT, True)
def __init__(self, name):
logging.Logger.__init__(self, name, logging.DEBUG)
color_formatter = ColoredFormatter(self.COLOR_FORMAT)
console = logging.StreamHandler()
console.setFormatter(color_formatter)
self.addHandler(console)
return
logging.setLoggerClass(ColoredLogger)
Run Code Online (Sandbox Code Playgroud)
以防万一其他人需要它.
如果您使用多个记录器或处理程序,请小心:ColoredFormatter
正在更改记录对象,该记录对象将进一步传递给其他处理程序或传播到其他记录程序.如果您已配置文件记录器等,则可能不希望在日志文件中包含颜色.为了避免这种情况,最好在返回格式化字符串之前简单地在操作levelname属性之前创建record
with 的副本copy.copy()
,或者将levelname重置为之前的值(在评论中记入Michael).
xol*_*lox 131
几年前我写了一个彩色的流处理程序供我自己使用.然后我遇到了这个页面,发现了一些人们正在复制/粘贴的代码片段:-(.我的流处理程序目前只适用于UNIX(Linux,Mac OS X),但优点是它可以在PyPI(和GitHub)上使用并且它使用起来很简单.它还有一个Vim语法模式:-).将来我可以将其扩展到Windows上.
要安装包:
$ pip install coloredlogs
Run Code Online (Sandbox Code Playgroud)
确认它是否有效:
$ coloredlogs --demo
Run Code Online (Sandbox Code Playgroud)
要开始使用您自己的代码:
$ python
> import coloredlogs, logging
> coloredlogs.install()
> logging.info("It works!")
2014-07-30 21:21:26 peter-macbook root[7471] INFO It works!
Run Code Online (Sandbox Code Playgroud)
上例中显示的默认日志格式包含日期,时间,主机名,记录器名称,PID,日志级别和日志消息.这就是它在实践中的样子:
sor*_*rin 71
这是一个适用于任何平台的解决方案.如果它不只是告诉我,我会更新它.
工作原理:在支持ANSI转义的平台上使用它们(非Windows),在Windows上,它确实使用API调用来更改控制台颜色.
该脚本会破坏标准库中的logging.StreamHandler.emit方法,为其添加包装器.
TestColorer.py
# Usage: add Colorer.py near you script and import it.
import logging
import Colorer
logging.warn("a warning")
logging.error("some error")
logging.info("some info")
Run Code Online (Sandbox Code Playgroud)
Colorer.py
#!/usr/bin/env python
# encoding: utf-8
import logging
# now we patch Python code to add color support to logging.StreamHandler
def add_coloring_to_emit_windows(fn):
# add methods we need to the class
def _out_handle(self):
import ctypes
return ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE)
out_handle = property(_out_handle)
def _set_color(self, code):
import ctypes
# Constants from the Windows API
self.STD_OUTPUT_HANDLE = -11
hdl = ctypes.windll.kernel32.GetStdHandle(self.STD_OUTPUT_HANDLE)
ctypes.windll.kernel32.SetConsoleTextAttribute(hdl, code)
setattr(logging.StreamHandler, '_set_color', _set_color)
def new(*args):
FOREGROUND_BLUE = 0x0001 # text color contains blue.
FOREGROUND_GREEN = 0x0002 # text color contains green.
FOREGROUND_RED = 0x0004 # text color contains red.
FOREGROUND_INTENSITY = 0x0008 # text color is intensified.
FOREGROUND_WHITE = FOREGROUND_BLUE|FOREGROUND_GREEN |FOREGROUND_RED
# winbase.h
STD_INPUT_HANDLE = -10
STD_OUTPUT_HANDLE = -11
STD_ERROR_HANDLE = -12
# wincon.h
FOREGROUND_BLACK = 0x0000
FOREGROUND_BLUE = 0x0001
FOREGROUND_GREEN = 0x0002
FOREGROUND_CYAN = 0x0003
FOREGROUND_RED = 0x0004
FOREGROUND_MAGENTA = 0x0005
FOREGROUND_YELLOW = 0x0006
FOREGROUND_GREY = 0x0007
FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified.
BACKGROUND_BLACK = 0x0000
BACKGROUND_BLUE = 0x0010
BACKGROUND_GREEN = 0x0020
BACKGROUND_CYAN = 0x0030
BACKGROUND_RED = 0x0040
BACKGROUND_MAGENTA = 0x0050
BACKGROUND_YELLOW = 0x0060
BACKGROUND_GREY = 0x0070
BACKGROUND_INTENSITY = 0x0080 # background color is intensified.
levelno = args[1].levelno
if(levelno>=50):
color = BACKGROUND_YELLOW | FOREGROUND_RED | FOREGROUND_INTENSITY | BACKGROUND_INTENSITY
elif(levelno>=40):
color = FOREGROUND_RED | FOREGROUND_INTENSITY
elif(levelno>=30):
color = FOREGROUND_YELLOW | FOREGROUND_INTENSITY
elif(levelno>=20):
color = FOREGROUND_GREEN
elif(levelno>=10):
color = FOREGROUND_MAGENTA
else:
color = FOREGROUND_WHITE
args[0]._set_color(color)
ret = fn(*args)
args[0]._set_color( FOREGROUND_WHITE )
#print "after"
return ret
return new
def add_coloring_to_emit_ansi(fn):
# add methods we need to the class
def new(*args):
levelno = args[1].levelno
if(levelno>=50):
color = '\x1b[31m' # red
elif(levelno>=40):
color = '\x1b[31m' # red
elif(levelno>=30):
color = '\x1b[33m' # yellow
elif(levelno>=20):
color = '\x1b[32m' # green
elif(levelno>=10):
color = '\x1b[35m' # pink
else:
color = '\x1b[0m' # normal
args[1].msg = color + args[1].msg + '\x1b[0m' # normal
#print "after"
return fn(*args)
return new
import platform
if platform.system()=='Windows':
# Windows does not support ANSI escapes and we are using API calls to set the console color
logging.StreamHandler.emit = add_coloring_to_emit_windows(logging.StreamHandler.emit)
else:
# all non-Windows platforms are supporting ANSI escapes so we use them
logging.StreamHandler.emit = add_coloring_to_emit_ansi(logging.StreamHandler.emit)
#log = logging.getLogger()
#log.addFilter(log_filter())
#//hdlr = logging.StreamHandler()
#//hdlr.setFormatter(formatter())
Run Code Online (Sandbox Code Playgroud)
rla*_*nte 65
更新:因为这是我长期以来一直想要抓住的一个痒,我继续为像我这样只想要简单方法做事的懒人写了一个库:zenlog
Colorlog非常适合这种情况.它可以在PyPI上使用(因此可以安装pip install colorlog
)并且可以主动维护.
这是一个快速复制和粘贴的代码片段,用于设置日志记录和打印体面的日志消息:
import logging
LOG_LEVEL = logging.DEBUG
LOGFORMAT = " %(log_color)s%(levelname)-8s%(reset)s | %(log_color)s%(message)s%(reset)s"
from colorlog import ColoredFormatter
logging.root.setLevel(LOG_LEVEL)
formatter = ColoredFormatter(LOGFORMAT)
stream = logging.StreamHandler()
stream.setLevel(LOG_LEVEL)
stream.setFormatter(formatter)
log = logging.getLogger('pythonConfig')
log.setLevel(LOG_LEVEL)
log.addHandler(stream)
log.debug("A quirky message only developers care about")
log.info("Curious users might want to know this")
log.warn("Something is wrong and any user should be informed")
log.error("Serious stuff, this is red for a reason")
log.critical("OH NO everything is on fire")
Run Code Online (Sandbox Code Playgroud)
输出:
小智 64
针对预定义日志级别的快速而脏的解决方案,无需定义新类.
logging.addLevelName( logging.WARNING, "\033[1;31m%s\033[1;0m" % logging.getLevelName(logging.WARNING))
logging.addLevelName( logging.ERROR, "\033[1;41m%s\033[1;0m" % logging.getLevelName(logging.ERROR))
Run Code Online (Sandbox Code Playgroud)
con*_* yu 22
Rich提供了一个日志处理程序,它将对 Python 日志模块编写的文本进行格式化和着色。
它易于使用且可定制,可在 cmd.exe、Windows Terminal、ConEmu和 Jupyter Notebook 中运行!(我尝试了很多软件包,我告诉你,只有rich的颜色可以在笔记本中使用。)。
Rich还带有许多其他精美的功能。
pip install rich
Run Code Online (Sandbox Code Playgroud)
import logging
from rich.logging import RichHandler
FORMAT = "%(message)s"
logging.basicConfig(
level="NOTSET", format=FORMAT, datefmt="[%X]", handlers=[RichHandler()]
) # set level=20 or logging.INFO to turn off debug
logger = logging.getLogger("rich")
logger.debug("debug...")
logger.info("info...")
logger.warning("warning...")
logger.error("error...")
logger.fatal("fatal...")
Run Code Online (Sandbox Code Playgroud)
KCJ*_*KCJ 16
好吧,我想我也可以添加我的彩色记录器的变化.
这并不奇怪,但它使用起来非常简单,并且不会更改记录对象,从而避免在使用文件处理程序时将ANSI转义序列记录到日志文件中.它不会影响日志消息格式.
如果您已经在使用日志记录模块的Formatter,那么要获得彩色级别名称,您只需要使用ColoredFormatter替换您的建议处理程序Formatter.如果您要记录整个应用程序,则只需要为顶级记录器执行此操作.
colored_log.py
#!/usr/bin/env python
from copy import copy
from logging import Formatter
MAPPING = {
'DEBUG' : 37, # white
'INFO' : 36, # cyan
'WARNING' : 33, # yellow
'ERROR' : 31, # red
'CRITICAL': 41, # white on red bg
}
PREFIX = '\033['
SUFFIX = '\033[0m'
class ColoredFormatter(Formatter):
def __init__(self, patern):
Formatter.__init__(self, patern)
def format(self, record):
colored_record = copy(record)
levelname = colored_record.levelname
seq = MAPPING.get(levelname, 37) # default white
colored_levelname = ('{0}{1}m{2}{3}') \
.format(PREFIX, seq, levelname, SUFFIX)
colored_record.levelname = colored_levelname
return Formatter.format(self, colored_record)
Run Code Online (Sandbox Code Playgroud)
app.py
#!/usr/bin/env python
import logging
from colored_log import ColoredFormatter
# Create top level logger
log = logging.getLogger("main")
# Add console handler using our custom ColoredFormatter
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
cf = ColoredFormatter("[%(name)s][%(levelname)s] %(message)s (%(filename)s:%(lineno)d)")
ch.setFormatter(cf)
log.addHandler(ch)
# Add file handler
fh = logging.FileHandler('app.log')
fh.setLevel(logging.DEBUG)
ff = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(ff)
log.addHandler(fh)
# Set log level
log.setLevel(logging.DEBUG)
# Log some stuff
log.debug("app has started")
log.info("Logging to 'app.log' in the script dir")
log.warning("This is my last warning, take heed")
log.error("This is an error")
log.critical("He's dead, Jim")
# Import a sub-module
import sub_module
Run Code Online (Sandbox Code Playgroud)
sub_module.py
#!/usr/bin/env python
import logging
log = logging.getLogger('main.sub_module')
log.debug("Hello from the sub module")
Run Code Online (Sandbox Code Playgroud)
终端输出
app.log内容
2017-09-29 00:32:23,434 - main - DEBUG - app has started
2017-09-29 00:32:23,434 - main - INFO - Logging to 'app.log' in the script dir
2017-09-29 00:32:23,435 - main - WARNING - This is my last warning, take heed
2017-09-29 00:32:23,435 - main - ERROR - This is an error
2017-09-29 00:32:23,435 - main - CRITICAL - He's dead, Jim
2017-09-29 00:32:23,435 - main.sub_module - DEBUG - Hello from the sub module
Run Code Online (Sandbox Code Playgroud)
当然,您可以根据需要设置格式化终端和日志文件输出.只有日志级别才会着色.
我希望有人觉得这很有用,而且不仅仅是太多了.:)
可以从这个GitHub Gist下载Python示例文件:https: //gist.github.com/KurtJacobson/48e750701acec40c7161b5a2f79e6bfd
cam*_*uni 15
我从airmind支持前景和背景标签更新了示例.只需在日志格式化程序字符串中使用颜色变量$ BLACK - $ WHITE.设置背景只需使用$ BG-BLACK - $ BG-WHITE.
import logging
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
COLORS = {
'WARNING' : YELLOW,
'INFO' : WHITE,
'DEBUG' : BLUE,
'CRITICAL' : YELLOW,
'ERROR' : RED,
'RED' : RED,
'GREEN' : GREEN,
'YELLOW' : YELLOW,
'BLUE' : BLUE,
'MAGENTA' : MAGENTA,
'CYAN' : CYAN,
'WHITE' : WHITE,
}
RESET_SEQ = "\033[0m"
COLOR_SEQ = "\033[1;%dm"
BOLD_SEQ = "\033[1m"
class ColorFormatter(logging.Formatter):
def __init__(self, *args, **kwargs):
# can't do super(...) here because Formatter is an old school class
logging.Formatter.__init__(self, *args, **kwargs)
def format(self, record):
levelname = record.levelname
color = COLOR_SEQ % (30 + COLORS[levelname])
message = logging.Formatter.format(self, record)
message = message.replace("$RESET", RESET_SEQ)\
.replace("$BOLD", BOLD_SEQ)\
.replace("$COLOR", color)
for k,v in COLORS.items():
message = message.replace("$" + k, COLOR_SEQ % (v+30))\
.replace("$BG" + k, COLOR_SEQ % (v+40))\
.replace("$BG-" + k, COLOR_SEQ % (v+40))
return message + RESET_SEQ
logging.ColorFormatter = ColorFormatter
Run Code Online (Sandbox Code Playgroud)
所以现在您可以在配置文件中简单地执行以下操作:
[formatter_colorFormatter]
class=logging.ColorFormatter
format= $COLOR%(levelname)s $RESET %(asctime)s $BOLD$COLOR%(name)s$RESET %(message)s
Run Code Online (Sandbox Code Playgroud)
max*_*zig 14
您可以导入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__)
Run Code Online (Sandbox Code Playgroud)
如果安装了colorlog模块并且输出实际上发送到终端,则代码仅启用日志消息中的颜色.这样可以避免在重定向日志输出时将转义序列写入文件.
此外,设置自定义颜色方案,更适合具有深色背景的终端.
一些示例记录调用:
log.debug ('Hello Debug')
log.info ('Hello Info')
log.warn ('Hello Warn')
log.error ('Hello Error')
log.critical('Hello Critical')
Run Code Online (Sandbox Code Playgroud)
输出:
小智 11
我将Sorin提供的原始示例和子类化的StreamHandler修改为ColorizedConsoleHandler.
他们的解决方案的缺点是它修改了消息,因为这正在修改实际的logmessage,任何其他处理程序也将获得修改后的消息.
由于我们使用多个记录器,因此在我们的案例中导致了带有颜色代码的日志文件.
下面的类只适用于支持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)
Run Code Online (Sandbox Code Playgroud)
Nic*_*ick 11
请看以下解决方案.流处理程序应该是着色的东西,然后你可以选择着色单词而不是整行(使用Formatter).
http://plumberjack.blogspot.com/2010/12/colorizing-logging-output-in-terminals.html
Mik*_*maa 10
现在有一个已发布的PyPi模块可用于可自定义的彩色日志输出:
https://pypi.python.org/pypi/rainbow_logging_handler/
和
https://github.com/laysakura/rainbow_logging_handler
支持Windows
支持Django
可定制的颜色
由于它是作为Python egg分发的,因此很容易为任何Python应用程序安装.
ToT*_*ire 10
pip install coloredlogs
Run Code Online (Sandbox Code Playgroud)
pip install coloredlogs
Run Code Online (Sandbox Code Playgroud)
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')
Run Code Online (Sandbox Code Playgroud)
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')
Run Code Online (Sandbox Code Playgroud)
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')
Run Code Online (Sandbox Code Playgroud)
%(asctime)s
- 发出日志记录调用时的时间作为人类可读的字符串%(created)f
- 发出记录调用时的浮点数时间%(filename)s
- 文件名%(funcName)s
- 包含日志记录调用的函数名称%(hostname)s
- 系统主机名%(levelname)s
- 文本记录级别%(levelno)s
- 整数记录级别%(lineno)d
- 发出日志记录调用的行号%(message)s
- 消息传递到日志记录调用(与 相同%(msg)s
)%(module)s
- 发出日志记录调用的不带扩展名的文件名%(msecs)d
- 发出记录调用时的毫秒部分时间%(msg)s
- 消息传递到日志记录调用(与 相同%(message)s
)%(name)s
- 记录器名称%(pathname)s
- 包含日志记录调用的文件的完整路径名%(process)d
- 进程ID%(processName)s
- 进程名称%(programname)s
- 系统程序名%(relativeCreated)d
- 发出日志记录调用时的时间(以毫秒为单位),相对于日志记录模块加载的时间%(thread)d
- 线程ID%(threadName)s
- 线程名称%(username)s
- 系统用户名定义一个班级
import logging
class CustomFormatter(logging.Formatter):
"""Logging Formatter to add colors and count warning / errors"""
grey = "\x1b[38;21m"
yellow = "\x1b[33;21m"
red = "\x1b[31;21m"
bold_red = "\x1b[31;1m"
reset = "\x1b[0m"
format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s (%(filename)s:%(lineno)d)"
FORMATS = {
logging.DEBUG: grey + format + reset,
logging.INFO: grey + format + reset,
logging.WARNING: yellow + format + reset,
logging.ERROR: red + format + reset,
logging.CRITICAL: bold_red + format + reset
}
def format(self, record):
log_fmt = self.FORMATS.get(record.levelno)
formatter = logging.Formatter(log_fmt)
return formatter.format(record)
Run Code Online (Sandbox Code Playgroud)
实例化记录器
# create logger with 'spam_application'
logger = logging.getLogger("My_app")
logger.setLevel(logging.DEBUG)
# create console handler with a higher log level
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
ch.setFormatter(CustomFormatter())
logger.addHandler(ch)
Run Code Online (Sandbox Code Playgroud)
并使用!
logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")
logger.critical("critical message")
Run Code Online (Sandbox Code Playgroud)
除了按级别着色之外,突出显示还使用交替颜色的日志消息参数怎么样?我最近为此编写了简单的代码。另一个优点是日志调用是使用 Python 3 大括号样式格式进行的。( "{}"
).
在此处查看最新代码和示例:https : //github.com/davidohana/colargulog
示例日志代码:
root_logger = logging.getLogger()
console_handler = logging.StreamHandler(stream=sys.stdout)
console_format = "%(asctime)s - %(levelname)-8s - %(name)-25s - %(message)s"
colored_formatter = ColorizedArgsFormatter(console_format)
console_handler.setFormatter(colored_formatter)
root_logger.addHandler(console_handler)
logger = logging.getLogger(__name__)
logger.info("Hello World")
logger.info("Request from {} handled in {:.3f} ms", socket.gethostname(), 11)
logger.info("Request from {} handled in {:.3f} ms", "127.0.0.1", 33.1)
logger.info("My favorite drinks are {}, {}, {}, {}", "milk", "wine", "tea", "beer")
logger.debug("this is a {} message", logging.getLevelName(logging.DEBUG))
logger.info("this is a {} message", logging.getLevelName(logging.INFO))
logger.warning("this is a {} message", logging.getLevelName(logging.WARNING))
logger.error("this is a {} message", logging.getLevelName(logging.ERROR))
logger.critical("this is a {} message", logging.getLevelName(logging.CRITICAL))
logger.info("Does old-style formatting also work? %s it is, but no colors (yet)", True)
Run Code Online (Sandbox Code Playgroud)
输出:
执行:
"""
colargulog - Python3 Logging with Colored Arguments and new string formatting style
Written by david.ohana@ibm.com
License: Apache-2.0
"""
import logging
import logging.handlers
import re
class ColorCodes:
grey = "\x1b[38;21m"
green = "\x1b[1;32m"
yellow = "\x1b[33;21m"
red = "\x1b[31;21m"
bold_red = "\x1b[31;1m"
blue = "\x1b[1;34m"
light_blue = "\x1b[1;36m"
purple = "\x1b[1;35m"
reset = "\x1b[0m"
class ColorizedArgsFormatter(logging.Formatter):
arg_colors = [ColorCodes.purple, ColorCodes.light_blue]
level_fields = ["levelname", "levelno"]
level_to_color = {
logging.DEBUG: ColorCodes.grey,
logging.INFO: ColorCodes.green,
logging.WARNING: ColorCodes.yellow,
logging.ERROR: ColorCodes.red,
logging.CRITICAL: ColorCodes.bold_red,
}
def __init__(self, fmt: str):
super().__init__()
self.level_to_formatter = {}
def add_color_format(level: int):
color = ColorizedArgsFormatter.level_to_color[level]
_format = fmt
for fld in ColorizedArgsFormatter.level_fields:
search = "(%\(" + fld + "\).*?s)"
_format = re.sub(search, f"{color}\\1{ColorCodes.reset}", _format)
formatter = logging.Formatter(_format)
self.level_to_formatter[level] = formatter
add_color_format(logging.DEBUG)
add_color_format(logging.INFO)
add_color_format(logging.WARNING)
add_color_format(logging.ERROR)
add_color_format(logging.CRITICAL)
@staticmethod
def rewrite_record(record: logging.LogRecord):
if not BraceFormatStyleFormatter.is_brace_format_style(record):
return
msg = record.msg
msg = msg.replace("{", "_{{")
msg = msg.replace("}", "_}}")
placeholder_count = 0
# add ANSI escape code for next alternating color before each formatting parameter
# and reset color after it.
while True:
if "_{{" not in msg:
break
color_index = placeholder_count % len(ColorizedArgsFormatter.arg_colors)
color = ColorizedArgsFormatter.arg_colors[color_index]
msg = msg.replace("_{{", color + "{", 1)
msg = msg.replace("_}}", "}" + ColorCodes.reset, 1)
placeholder_count += 1
record.msg = msg.format(*record.args)
record.args = []
def format(self, record):
orig_msg = record.msg
orig_args = record.args
formatter = self.level_to_formatter.get(record.levelno)
self.rewrite_record(record)
formatted = formatter.format(record)
# restore log record to original state for other handlers
record.msg = orig_msg
record.args = orig_args
return formatted
class BraceFormatStyleFormatter(logging.Formatter):
def __init__(self, fmt: str):
super().__init__()
self.formatter = logging.Formatter(fmt)
@staticmethod
def is_brace_format_style(record: logging.LogRecord):
if len(record.args) == 0:
return False
msg = record.msg
if '%' in msg:
return False
count_of_start_param = msg.count("{")
count_of_end_param = msg.count("}")
if count_of_start_param != count_of_end_param:
return False
if count_of_start_param != len(record.args):
return False
return True
@staticmethod
def rewrite_record(record: logging.LogRecord):
if not BraceFormatStyleFormatter.is_brace_format_style(record):
return
record.msg = record.msg.format(*record.args)
record.args = []
def format(self, record):
orig_msg = record.msg
orig_args = record.args
self.rewrite_record(record)
formatted = self.formatter.format(record)
# restore log record to original state for other handlers
record.msg = orig_msg
record.args = orig_args
return formatted
Run Code Online (Sandbox Code Playgroud)
有很多回应.但没有人在谈论装饰者.所以这是我的.
因为它更简单.
不需要导入任何东西,也不需要编写任何子类:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import logging
NO_COLOR = "\33[m"
RED, GREEN, ORANGE, BLUE, PURPLE, LBLUE, GREY = \
map("\33[%dm".__mod__, range(31, 38))
logging.basicConfig(format="%(message)s", level=logging.DEBUG)
logger = logging.getLogger(__name__)
# the decorator to apply on the logger methods info, warn, ...
def add_color(logger_method, color):
def wrapper(message, *args, **kwargs):
return logger_method(
# the coloring is applied here.
color+message+NO_COLOR,
*args, **kwargs
)
return wrapper
for level, color in zip((
"info", "warn", "error", "debug"), (
GREEN, ORANGE, RED, BLUE
)):
setattr(logger, level, add_color(getattr(logger, level), color))
# this is displayed in red.
logger.error("Launching %s." % __file__)
Run Code Online (Sandbox Code Playgroud)
这将错误设置为红色,将调试消息设置为蓝色,等等.就像问题中的问题一样.
我们甚至可以调整包装器来使用color
动态设置消息颜色的参数logger.debug("message", color=GREY)
编辑:所以这里是适应装饰器在运行时设置颜色:
def add_color(logger_method, _color):
def wrapper(message, *args, **kwargs):
color = kwargs.pop("color", _color)
if isinstance(color, int):
color = "\33[%dm" % color
return logger_method(
# the coloring is applied here.
color+message+NO_COLOR,
*args, **kwargs
)
return wrapper
# blah blah, apply the decorator...
# this is displayed in red.
logger.error("Launching %s." % __file__)
# this is displayed in blue
logger.error("Launching %s." % __file__, color=34)
# and this, in grey
logger.error("Launching %s." % __file__, color=GREY)
Run Code Online (Sandbox Code Playgroud)
安装 colorlog 包,您可以立即在日志消息中使用颜色:
logger
实例,就像您通常所做的那样。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")
Run Code Online (Sandbox Code Playgroud)
只需更新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'))
Run Code Online (Sandbox Code Playgroud)
包裹:
pip install colorlog
Run Code Online (Sandbox Code Playgroud)
输出:
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
Run Code Online (Sandbox Code Playgroud)
airmind方法的另一个小混音,将所有内容保持在一个类中:
class ColorFormatter(logging.Formatter):
FORMAT = ("[$BOLD%(name)-20s$RESET][%(levelname)-18s] "
"%(message)s "
"($BOLD%(filename)s$RESET:%(lineno)d)")
BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8)
RESET_SEQ = "\033[0m"
COLOR_SEQ = "\033[1;%dm"
BOLD_SEQ = "\033[1m"
COLORS = {
'WARNING': YELLOW,
'INFO': WHITE,
'DEBUG': BLUE,
'CRITICAL': YELLOW,
'ERROR': RED
}
def formatter_msg(self, msg, use_color = True):
if use_color:
msg = msg.replace("$RESET", self.RESET_SEQ).replace("$BOLD", self.BOLD_SEQ)
else:
msg = msg.replace("$RESET", "").replace("$BOLD", "")
return msg
def __init__(self, use_color=True):
msg = self.formatter_msg(self.FORMAT, use_color)
logging.Formatter.__init__(self, msg)
self.use_color = use_color
def format(self, record):
levelname = record.levelname
if self.use_color and levelname in self.COLORS:
fore_color = 30 + self.COLORS[levelname]
levelname_color = self.COLOR_SEQ % fore_color + levelname + self.RESET_SEQ
record.levelname = levelname_color
return logging.Formatter.format(self, record)
Run Code Online (Sandbox Code Playgroud)
要使用将格式化程序附加到处理程序,例如:
handler.setFormatter(ColorFormatter())
logger.addHandler(handler)
Run Code Online (Sandbox Code Playgroud)
您可以用于\xe2\x9a\xa0\xef\xb8\x8f
警告消息和错误消息。
或者简单地使用这些笔记本作为颜色:
\nprint(": error message")\nprint(": warning message")\nprint(": ok status message")\nprint(": action message")\nprint(": canceled status message")\nprint(": Or anything you like and want to recognize immediately by color")\n
Run Code Online (Sandbox Code Playgroud)\n\n这种方法还可以帮助您直接在源代码中快速扫描和查找日志。
\n窗户: win +.
\nlinux: control +.或 control+;
\n小智 5
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)))`
Run Code Online (Sandbox Code Playgroud)
用于着色任何终端文本的简单但非常灵活的工具是" colout ".
pip install colout
myprocess | colout REGEX_WITH_GROUPS color1,color2...
Run Code Online (Sandbox Code Playgroud)
'myprocess'输出中与正则表达式组1匹配的任何文本将使用color1,第2组使用color2等进行着色.
例如:
tail -f /var/log/mylogfile | colout '^(\w+ \d+ [\d:]+)|(\w+\.py:\d+ .+\(\)): (.+)$' white,black,cyan bold,bold,normal
Run Code Online (Sandbox Code Playgroud)
即第一个正则表达式组(parens)匹配日志文件中的初始日期,第二个组匹配python文件名,行号和函数名称,第三个组匹配之后的日志消息.我还使用'粗体/法线'的并行序列以及颜色序列.这看起来像:
请注意,与我的任何正则表达式不匹配的行或部分行仍然会回显,因此这不像'grep --color' - 没有任何内容从输出中过滤掉.
显然这很灵活,你可以在任何进程中使用它,而不仅仅是拖尾日志文件.我通常只要想要为某些东西着色,就可以动态地制作一个新的正则表达式.出于这个原因,我更喜欢colout到任何自定义日志文件着色工具,因为我只需要学习一个工具,无论我着色的是什么:日志,测试输出,语法突出显示终端中的代码片段等.
它还避免在日志文件本身中实际转储ANSI代码,这是一个坏主意,因为它会破坏日志文件中的模式,除非你总是记得匹配grep正则表达式中的ANSI代码.
我很高兴能分享这个灵活的原木着色解决方案。我认为这是@SergeyPleshakov对此解决方案的改进。我利用了日志记录的额外 kwargs来设置日志前缀和后缀。然后我们只需默认前缀和后缀以与日志级别相对应的终端颜色代码开始和结束。
\n奖励功能 \xe2\x9c\xa8 \xe2\x9c\xa8
\n额外的prefix
andsuffix
可以被日志调用覆盖为任何内容。您希望调试日志带有前缀,为什么不呢。您希望其中一个信息日志为绿色而不是默认值,那就去做吧!
定义终端Color
并ColorLogFormatter
类
import logging\n\n\nclass Color:\n """A class for terminal color codes."""\n\n BOLD = "\\033[1m"\n BLUE = "\\033[94m"\n WHITE = "\\033[97m"\n GREEN = "\\033[92m"\n YELLOW = "\\033[93m"\n RED = "\\033[91m"\n BOLD_WHITE = BOLD + WHITE\n BOLD_BLUE = BOLD + BLUE\n BOLD_GREEN = BOLD + GREEN\n BOLD_YELLOW = BOLD + YELLOW\n BOLD_RED = BOLD + RED\n END = "\\033[0m"\n\n\nclass ColorLogFormatter(logging.Formatter):\n """A class for formatting colored logs."""\n\n FORMAT = "%(prefix)s%(msg)s%(suffix)s"\n\n LOG_LEVEL_COLOR = {\n "DEBUG": {\'prefix\': \'\', \'suffix\': \'\'},\n "INFO": {\'prefix\': \'\', \'suffix\': \'\'},\n "WARNING": {\'prefix\': Color.BOLD_YELLOW, \'suffix\': Color.END},\n "ERROR": {\'prefix\': Color.BOLD_RED, \'suffix\': Color.END},\n "CRITICAL": {\'prefix\': Color.BOLD_RED, \'suffix\': Color.END},\n }\n\n def format(self, record):\n """Format log records with a default prefix and suffix to terminal color codes that corresponds to the log level name."""\n if not hasattr(record, \'prefix\'):\n record.prefix = self.LOG_LEVEL_COLOR.get(record.levelname.upper()).get(\'prefix\')\n \n if not hasattr(record, \'suffix\'):\n record.suffix = self.LOG_LEVEL_COLOR.get(record.levelname.upper()).get(\'suffix\')\n\n formatter = logging.Formatter(self.FORMAT)\n return formatter.format(record)\n
Run Code Online (Sandbox Code Playgroud)\n实例化记录器
\nlogger = logging.getLogger(\'bobcat\')\nlogger.setLevel(\'DEBUG\')\n\nstream_handler = logging.StreamHandler()\nstream_handler.setFormatter(ColorLogFormatter())\nlogger.addHandler(stream_handler)\n
Run Code Online (Sandbox Code Playgroud)\n并使用!
\n logger.debug("This is debug", extra={\'prefix\': \' \'})\n logger.info("This is info")\n logger.info("This is a green info", extra={\'prefix\': Color.GREEN, \'suffix\': Color.END})\n logger.warning("This is warning")\n logger.error("This is error")\n logger.critical("This is critical")\n
Run Code Online (Sandbox Code Playgroud)\n瞧\xc3\xa0!
\n\n如果你不想发明轮子就好了。
就pip install loguru
在那时:
from loguru import logger
if __name__ == '__main__':
message = "Message text"
logger.info(message)
logger.debug(message)
logger.warning(message)
logger.success(message)
logger.error(message)
logger.critical(message)
Run Code Online (Sandbox Code Playgroud)
您可以更改格式、颜色、从框中写入文件...这是文档
归档时间: |
|
查看次数: |
141966 次 |
最近记录: |