根据Python3中的消息日志记录级别修改日志消息格式

JS.*_*JS. 11 logging python-3.x

在这里问了python 2的这个问题,但是当Python 3.2.3的答案不再有效时再次遇到了问题.

这里的代码适用于Python 2.7.3:

import logging

# Attempt to set up a Python3 logger than will print custom messages
# based on each message's logging level.
# The technique recommended for Python2 does not appear to work for
# Python3

class CustomConsoleFormatter(logging.Formatter):
    """
    Modify the way DEBUG messages are displayed.

    """
    def __init__(self, fmt="%(levelno)d: %(msg)s"):
        logging.Formatter.__init__(self, fmt=fmt)

    def format(self, record):

        # Remember the original format
        format_orig = self._fmt

        if record.levelno == logging.DEBUG:
            self._fmt = "DEBUG: %(msg)s"

        # Call the original formatter to do the grunt work
        result = logging.Formatter.format(self, record)

        # Restore the original format
        self._fmt = format_orig

        return result


# Set up a logger
my_logger = logging.getLogger("my_custom_logger")
my_logger.setLevel(logging.DEBUG)

my_formatter = CustomConsoleFormatter()

console_handler = logging.StreamHandler()
console_handler.setFormatter(my_formatter)

my_logger.addHandler(console_handler)

my_logger.debug("This is a DEBUG-level message")
my_logger.info("This is an INFO-level message")
Run Code Online (Sandbox Code Playgroud)

使用Python 2.7.3运行:

tcsh-16: python demo_python_2.7.3.py 
DEBUG: This is a DEBUG-level message
20: This is an INFO-level message
Run Code Online (Sandbox Code Playgroud)


据我所知,转换为Python3只需要一个稍微修改CustomConsoleFormatter.init():

def __init__(self):
    super().__init__(fmt="%(levelno)d: %(msg)s", datefmt=None, style='%')
Run Code Online (Sandbox Code Playgroud)

在Python 3.2.3上:

tcsh-26: python3 demo_python_3.2.3.py
10: This is a DEBUG-level message
20: This is an INFO-level message
Run Code Online (Sandbox Code Playgroud)


正如你所看到的,我想用'DEBUG'代替'10'的愿望被挫败了.

我已经尝试在Python3源码中进行挖掘,看起来PercentStyle实例化在我之后破坏了self._fmt,好吧,我自己就破坏了它.

我的伐木剁停止了能够解决这种皱纹.

任何人都可以推荐另一种方式或者指出我忽略的东西吗?

JS.*_*JS. 15

通过一些挖掘,我能够修改Python 2解决方案以使用Python 3.在Python2中,有必要暂时覆盖Formatter._fmt.在Python3中,对多种格式字符串类型的支持要求我们临时覆盖Formatter._style._fmt.

# Custom formatter
class MyFormatter(logging.Formatter):

    err_fmt  = "ERROR: %(msg)s"
    dbg_fmt  = "DBG: %(module)s: %(lineno)d: %(msg)s"
    info_fmt = "%(msg)s"

    def __init__(self):
        super().__init__(fmt="%(levelno)d: %(msg)s", datefmt=None, style='%')  

    def format(self, record):

        # Save the original format configured by the user
        # when the logger formatter was instantiated
        format_orig = self._style._fmt

        # Replace the original format with one customized by logging level
        if record.levelno == logging.DEBUG:
            self._style._fmt = MyFormatter.dbg_fmt

        elif record.levelno == logging.INFO:
            self._style._fmt = MyFormatter.info_fmt

        elif record.levelno == logging.ERROR:
            self._style._fmt = MyFormatter.err_fmt

        # Call the original formatter class to do the grunt work
        result = logging.Formatter.format(self, record)

        # Restore the original format configured by the user
        self._style._fmt = format_orig

        return result
Run Code Online (Sandbox Code Playgroud)

这里是Halloleo的例子,说明如何在你的脚本中使用上述内容(来自这个问题Python2版本):

fmt = MyFormatter()
hdlr = logging.StreamHandler(sys.stdout)

hdlr.setFormatter(fmt)
logging.root.addHandler(hdlr)
logging.root.setLevel(DEBUG)
Run Code Online (Sandbox Code Playgroud)


sez*_*zeb 11

我更喜欢这个,因为它更短、更简单,并且不需要像“ERROR”这样的字符串进行硬编码。无需重置._fmt,因为else:可以很好地处理。

另外,使用"%(msg)s"不适用于惰性日志记录!

class Formatter(logging.Formatter):
    def format(self, record):
        if record.levelno == logging.INFO:
            self._style._fmt = "%(message)s"
        else:
            self._style._fmt = "%(levelname)s: %(message)s"
        return super().format(record)
Run Code Online (Sandbox Code Playgroud)

使用示例:

import logging

logger = logging.getLogger()
handler = logging.StreamHandler()
handler.setFormatter(Formatter())
logger.setLevel(logging.DEBUG)
logger.addHandler(handler)

logger.debug('foo')
logger.info('bar %d', 4)
Run Code Online (Sandbox Code Playgroud)
DEBUG: foo
bar 4
Run Code Online (Sandbox Code Playgroud)

如果您想让关卡名称着色:

DEBUG: foo
bar 4
Run Code Online (Sandbox Code Playgroud)

请参阅https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit了解颜色编号