如何为Python日志输出着色?

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属性之前创建recordwith 的副本copy.copy(),或者将levelname重置为之前的值(在评论中记入Michael).

  • 我不相信你应该为此创建一个记录器子类 - 你的答案很好,只要创建一个专门的`Formatter`并在`StreamHandler`上指定它的使用.但是不需要记录器子类.实际上,使用logger类会为每个创建的记录器添加一个处理程序,这不是您通常想要的. (50认同)
  • "ColoredFormatter"的一面注释.它正在更改记录对象,该记录对象将进一步传递给其他处理程序或传播到其他记录程序.如果您已配置文件记录器等,则可能不希望在日志文件中包含颜色.为了避免这种情况,在返回格式化字符串之前,最好在操作levelname属性之前简单地创建带有`copy.copy()`的`record`副本,或者将levelname重置为之前的值. (6认同)
  • @simon:http://plumberjack.blogspot.co.uk/2010/12/colorizing-logging-output-in-terminals.html (3认同)
  • @Swaroop - 这些是 ANSI 转义码,您可以在 Google 上查找,或者在这里找到:http://en.wikipedia.org/wiki/ANSI_escape_code,或者 http://pueblo.sourceforge.net/doc/手册/ansi_color_codes.html (2认同)

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,日志级别和日志消息.这就是它在实践中的样子:

有色日志输出的屏幕截图

  • 这看起来很漂亮.不幸的是,它破坏了很多东西; 特别是,它使对logging.basicConfig的调用无效.例如,这使得无法使用自定义格式化程序. (9认同)
  • 很有趣,我只是想在这个帖子中添加一个链接到"https://pypi.python.org/pypi/coloredlogs/0.4.7"! (2认同)
  • 仅供参考:较新版本的 colorlogs 包使用自定义格式化程序来注入 ANSI 转义序列。此自定义格式化程序支持用户定义的日志格式,与 Python 的日志记录模块相同。然而,我不明白如何将 colorlogs 与用户定义的格式化程序结合起来,这违背了包的设计。 (2认同)
  • 做得太好了!!从今天开始,它在 Windows 中的运行就像梦想一样:) (2认同)

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)

  • 我基于此编写了一个StreamHandler类,请参阅https://gist.github.com/mooware/a1ed40987b6cc9ab9c65. (3认同)
  • 这对我有用!第90行:应为args [1] .msg = color + str(args [1] .msg)+'\ x1b [0m'#normal”。 (2认同)

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)

输出:

Colorlog输出

  • 很好的答案; +1.可以修剪代码示例(真的需要三次调用`setLevel`吗?) (4认同)
  • 我希望如果我花足够长的时间研究这些答案,我能找到这样的答案。☺ 我希望@airmind 会考虑将其作为公认的答案,以便未来的工作聪明的人可以找到似乎是最佳懒惰的最佳图书馆。 (2认同)
  • 我刚刚为输出的消息示例投了赞成票^^ (2认同)

小智 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)

  • 应用和理解最简单,最干净的解决方案. (3认同)
  • 小改进:将此代码放在 `if sys.sdterr.isatty():` 中。在这种情况下,如果您将输出重定向到文件,文件将不包含这些转义字符。 (3认同)
  • 由于只有日志级别的名称是彩色的,因此您必须确保将日志级别名称打印到控制台.这对我来说不是开箱即用的.这些方面的内容将有所帮助:`logging.basicConfig(format ='%(asctime)s [%(name)s] [%(levelname)s]%(message)s')`当然`%(levelnames) )s`很重要. (2认同)

con*_* yu 22

使用丰富的库

Rich提供了一个日志处理程序,它将对 Python 日志模块编写的文本进行格式化和着色。

它易于使用且可定制,可在 cmd.exe、Windows TerminalConEmu和 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)

终端截图

  • 或者只需执行“python -m rich.logging”即可查看不同用例的示例:-) (5认同)

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

  • 顺便说一句,要为消息本身添加颜色,只需在return之前添加以下行:colored_record.msg =('{0} {1} m {2} {3}')。format(self.PREFIX,seq,colored_record。 getMessage(),self.SUFFIX)` (2认同)

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)

输出:

在此输入图像描述

  • 也可以使用`colorlog.basicConfig`代替`logging.basicConfig`,它有一些很好的默认值 (2认同)

小智 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- 系统用户名

资料来源:

彩色原木包

日志库


Ser*_*kov 8

2019代码,无需其他软件包,Python 3

定义一个班级

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)

结果 在此处输入图片说明

  • 哎呀,刚刚玩了一下并找到了解决方案,只需将 `...21m` 更改为 `20m` 似乎在我的系统中工作得很好。以防万一有人遇到同样的问题。 (7认同)
  • 我非常喜欢这个答案,因此我为其制作了一个 [repo](https://github.com/t177398/best_python_logger),其中包含一些增量和 ansi 颜色的备忘单。 (3认同)
  • 我运行测试(python 3.7,Windows),但日志记录不显示颜色: `←[38;21m2019-11-12 19:29:50,994 - My_app - DEBUG - 调试消息 (test_colored_log.py:43)←[ 0m ←[38;21m2019-11-12 19:29:50,994 - My_app - 信息 - 信息消息 (test_colored_log.py:44)←[0m ←[33;21m2019-11-12 19:29:50,994 - My_app - 警告- 警告消息 (test_colored_log.py:45)←[0m ←[31;21m2019-11-12 19:29:50,994 - My_app - 错误 - 错误消息 (test_colored_log.py:46)←[0m ←[31;1m2019- 11-12 19:29:50,994 - My_app - CRITICAL - 关键消息 (test_colored_log.py:47)←[0m` (2认同)
  • 我喜欢这个例子,但是你的“logging.setLevel()”调用错误。使用如图所示的代码,调用“logger.info()”将不会输出任何内容。需要在“logger”对象上调用“setLevel()”,而不是在“ch”处理程序上调用。 (2认同)

dux*_*ux2 8

除了按级别着色之外,突出显示还使用交替颜色的日志消息参数怎么样?我最近为此编写了简单的代码。另一个优点是日志调用是使用 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)


lai*_*ain 7

有很多回应.但没有人在谈论装饰者.所以这是我的.

因为它更简单.

不需要导入任何东西,也不需要编写任何子类:

#!/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)


Mil*_*vić 7

安装 colorlog 包,您可以立即在日志消息中使用颜色:

  • 获取一个logger实例,就像您通常所做的那样。
  • 设置日志级别。您还可以直接使用来自日志记录模块的常量,如DEBUGINFO
  • 将消息格式化程序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)


gra*_*ion 6

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)


Moj*_*ini 6

表情符号

\n

您可以用于\xe2\x9a\xa0\xef\xb8\x8f警告消息和错误消息。

\n

或者简单地使用这些笔记本作为颜色:

\n
print(": 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

这种方法还可以帮助您直接在源代码中快速扫描和查找日志。

\n
\n

如何打开表情符号选择器?

\n

苹果 电脑control ++commandspace

\n

窗户 win +.

\n

linux 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)


Jon*_*ley 5

用于着色任何终端文本的简单但非常灵活的工具是" 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代码.


Aid*_*len 5

使用标准Python3日志库的解决方案

\n

我很高兴能分享这个灵活的原木着色解决方案。我认为这是@SergeyPleshakov对此解决方案的改进。我利用了日志记录的额外 kwargs来设置日志前缀和后缀。然后我们只需默认前缀和后缀以与日志级别相对应的终端颜色代码开始和结束。

\n

奖励功能 \xe2\x9c\xa8 \xe2\x9c\xa8

\n

额外的prefixandsuffix可以被日志调用覆盖为任何内容。您希望调试日志带有前缀,为什么不呢。您希望其中一个信息日志为绿色而不是默认值,那就去做吧!

\n

定义终端ColorColorLogFormatter

\n
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

实例化记录器

\n
logger = 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


Ron*_*nin 5

如果你不想发明轮子就好了。

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)

输出: 在此输入图像描述

您可以更改格式、颜色、从框中写入文件...这是文档