Python的日志格式可以根据消息日志级别修改吗?

98 投票
8 回答
36119 浏览
提问于 2025-04-15 13:55

我正在使用Python的logging机制来在屏幕上打印输出。虽然我可以用print语句来实现这个功能,但我希望能让用户更灵活地选择关闭某些类型的输出。我喜欢错误信息的打印格式,但在输出级别为“信息”时,我希望格式能简单一些。

举个例子:

  logger.error("Running cmd failed")
  logger.info("Running cmd passed")

在这个例子中,我希望错误信息的打印格式能有所不同:

# error
Aug 27, 2009 - ERROR: Running cmd failed
# info
Running cmd passed

有没有办法在不创建多个日志对象的情况下,为不同的日志级别设置不同的格式?我希望在创建日志器后不再修改它,因为有很多if/else语句来决定输出应该如何记录。

8 个回答

23

一种实现方法

定义一个类

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)

创建一个日志记录器

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

然后使用它!

logger.debug("debug message")
logger.info("info message")
logger.warning("warning message")
logger.error("error message")
logger.critical("critical message")

结果 在这里输入图片描述

97

我刚遇到这个问题,填补上面例子中留下的“空白”有点困难。这是我用的一个更完整、可运行的版本。希望这能帮助到某些人:

# 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, fmt="%(levelno)s: %(msg)s"):
        logging.Formatter.__init__(self, fmt)


    def format(self, record):

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

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

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

        elif record.levelno == logging.ERROR:
            self._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._fmt = format_orig

        return result

补充:

感谢Halloleo,这里有一个如何在你的脚本中使用上面内容的例子:

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

hdlr.setFormatter(fmt)
logging.root.addHandler(hdlr)
logging.root.setLevel(DEBUG)

补充 2:

Python3的日志记录有了一些变化。想了解Python3的做法,可以查看这里

33

是的,你可以通过创建一个自定义的 Formatter 类来实现这个功能:

class MyFormatter(logging.Formatter):
    def format(self, record):
        #compute s according to record.levelno
        #for example, by setting self._fmt
        #according to the levelno, then calling
        #the superclass to do the actual formatting
        return s

然后把一个 MyFormatter 的实例连接到你的处理程序上。

撰写回答