日志记录、 StreamHandler和标准流

我无法弄清楚如何将信息级别的消息记录到 stdout,但其他一切都记录到 stderr。我已经读过这个http://docs.python.org/library/logging.html。有什么建议吗?

我无法弄清楚如何将信息级别的消息记录到 stdout,但其他一切都记录到 stderr。我已经读过这个http://docs.python.org/library/logging.html。有什么建议吗?

125

以下脚本log1.py

import logging, sys
class SingleLevelFilter(logging.Filter):
    def __init__(self, passlevel, reject):
        self.passlevel = passlevel
        self.reject = reject
    def filter(self, record):
        if self.reject:
            return (record.levelno != self.passlevel)
        else:
            return (record.levelno == self.passlevel)
h1 = logging.StreamHandler(sys.stdout)
f1 = SingleLevelFilter(logging.INFO, False)
h1.addFilter(f1)
rootLogger = logging.getLogger()
rootLogger.addHandler(h1)
h2 = logging.StreamHandler(sys.stderr)
f2 = SingleLevelFilter(logging.INFO, True)
h2.addFilter(f2)
rootLogger.addHandler(h2)
logger = logging.getLogger("my.logger")
logger.setLevel(logging.DEBUG)
logger.debug("A DEBUG message")
logger.info("An INFO message")
logger.warning("A WARNING message")
logger.error("An ERROR message")
logger.critical("A CRITICAL message")

运行时,会产生以下结果。

C:\temp>log1.py
A DEBUG message
An INFO message
A WARNING message
An ERROR message
A CRITICAL message

正如你所期望的,因为在终端上sys.stdoutsys.stderr是相同的。现在,让我们将 stdout 重定向到一个文件,tmp

C:\temp>log1.py >tmp
A DEBUG message
A WARNING message
An ERROR message
A CRITICAL message

因此,INFO 消息尚未打印到终端-但指向sys.stderr的消息已打印。让我们看看tmp中的内容:

C:\temp>type tmp
An INFO message

所以这种方法似乎做你想要的。

20

通常,我认为将低于WARNING的消息重定向到stdout而不是仅INFO消息是有意义的。

根据Vinay Sajip的优秀答案,我想出了这个:

class MaxLevelFilter(Filter):
    '''Filters (lets through) all messages with level < LEVEL'''
    def __init__(self, level):
        self.level = level
    def filter(self, record):
        return record.levelno < self.level # "<" instead of "<=": since logger.setLevel is inclusive, this should be exclusive
MIN_LEVEL= DEBUG
#...
stdout_hdlr = StreamHandler(sys.stdout)
stderr_hdlr = StreamHandler(sys.stderr)
lower_than_warning= MaxLevelFilter(WARNING)
stdout_hdlr.addFilter( lower_than_warning )     #messages lower than WARNING go to stdout
stdout_hdlr.setLevel( MIN_LEVEL )
stderr_hdlr.setLevel( max(MIN_LEVEL, WARNING) ) #messages >= WARNING ( and >= STDOUT_LOG_LEVEL ) go to stderr
#...
15

由于我的编辑被拒绝,这里是我的答案。@ goncalopp 的答案是好的,但不独立或开箱即用。这是我的改进版本:

import sys, logging
class LogFilter(logging.Filter):
    """Filters (lets through) all messages with level < LEVEL"""
    # http://stackoverflow.com/a/24956305/408556
    def __init__(self, level):
        self.level = level
    def filter(self, record):
        # "<" instead of "<=": since logger.setLevel is inclusive, this should
        # be exclusive
        return record.levelno < self.level
MIN_LEVEL = logging.DEBUG
stdout_hdlr = logging.StreamHandler(sys.stdout)
stderr_hdlr = logging.StreamHandler(sys.stderr)
log_filter = LogFilter(logging.WARNING)
stdout_hdlr.addFilter(log_filter)
stdout_hdlr.setLevel(MIN_LEVEL)
stderr_hdlr.setLevel(max(MIN_LEVEL, logging.WARNING))
# messages lower than WARNING go to stdout
# messages >= WARNING (and >= STDOUT_LOG_LEVEL) go to stderr
rootLogger = logging.getLogger()
rootLogger.addHandler(stdout_hdlr)
rootLogger.addHandler(stderr_hdlr)
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# Example Usage
>>> logger.debug("A DEBUG message")
>>> logger.info("An INFO message")
>>> logger.warning("A WARNING message")
>>> logger.error("An ERROR message")
>>> logger.critical("A CRITICAL message")
1

将彩色输出发送到 stderr 的最简单的处理程序:

class ColorStderr(logging.StreamHandler):
    def __init__(self):
        class AddColor(logging.Formatter):
            def format(self, record: logging.LogRecord):
                msg = super().format(record)
                # Green/Cyan/Yellow/Red/Redder based on log level:
                color = '\033[1;' + ('32m', '36m', '33m', '31m', '41m')[
                   min(4,int(4 * record.levelno / logging.FATAL))]
                return color + record.levelname + '\033[1;0m: ' + msg
        super().__init__(sys.stderr)
        self.setFormatter(AddColor())

与一起使用:

logging.basicConfig(level=logging.INFO, handlers=[ColorStderr()])

或者,您甚至可以将格式化程序直接应用于当前日志处理程序,而无需ColorStderr

logging.getLogger().handlers[0].setFormatter(AddColor())

本站系公益性非盈利分享网址,本文来自用户投稿,不代表码文网立场,如若转载,请注明出处

(286)
为什么我的共享库中存在展开符号(symbols in unwind)
下一篇

相关推荐

发表评论

登录 后才能评论

评论列表(44条)