如何将INFO和DEBUG日志信息发送到stdout,而将更高等级的信息发送到stderr

41 投票
9 回答
21528 浏览
提问于 2025-04-15 19:31

有没有简单的方法可以用Python的日志模块,把DEBUG或INFO级别的信息和更高级别的信息发送到不同的地方?

这样做是否合理呢?

9 个回答

7

为了方便起见,这里把所有内容都放在一个包里,使用格式化工具:

# shared formatter, but you can use separate ones:
FORMAT = '%(asctime)s - %(name)s - %(levelname)s - %(threadName)s - %(message)s'
formatter = logging.Formatter(FORMAT)

# single app logger:
log = logging.getLogger(__name__)
log.setLevel(logging.INFO)

# 2 handlers for the same logger:
h1 = logging.StreamHandler(sys.stdout)
h1.setLevel(logging.DEBUG)
# filter out everything that is above INFO level (WARN, ERROR, ...)
h1.addFilter(lambda record: record.levelno <= logging.INFO)
h1.setFormatter(formatter)
log.addHandler(h1)

h2 = logging.StreamHandler(sys.stderr)
# take only warnings and error logs
h2.setLevel(logging.WARNING)
h2.setFormatter(formatter)
log.addHandler(h2)

# profit:
log.info(...)
log.debug(...)

我的需求是把标准输出(也就是程序正常运行时的输出)重定向到一个数据文件里,同时在处理过程中能在屏幕上看到错误信息。

42
import logging
import sys

class LessThanFilter(logging.Filter):
    def __init__(self, exclusive_maximum, name=""):
        super(LessThanFilter, self).__init__(name)
        self.max_level = exclusive_maximum

    def filter(self, record):
        #non-zero return means we log this message
        return 1 if record.levelno < self.max_level else 0

#Get the root logger
logger = logging.getLogger()
#Have to set the root logger level, it defaults to logging.WARNING
logger.setLevel(logging.NOTSET)

logging_handler_out = logging.StreamHandler(sys.stdout)
logging_handler_out.setLevel(logging.DEBUG)
logging_handler_out.addFilter(LessThanFilter(logging.WARNING))
logger.addHandler(logging_handler_out)

logging_handler_err = logging.StreamHandler(sys.stderr)
logging_handler_err.setLevel(logging.WARNING)
logger.addHandler(logging_handler_err)

#demonstrate the logging levels
logger.debug('DEBUG')
logger.info('INFO')
logger.warning('WARNING')
logger.error('ERROR')
logger.critical('CRITICAL')

抛开具体的实现不谈,我觉得在Python中使用日志功能来输出信息到终端是个好主意。特别是你可以添加一个额外的处理器,把日志信息也记录到一个文件里。如果你把标准输出的级别设置为INFO而不是DEBUG,那么你甚至可以在日志文件中包含一些用户通常看不到的额外DEBUG信息。

-4

这不一定是个好主意(因为把信息和调试消息混在正常输出里可能会让人感到困惑!),不过是可行的。你可以有多个处理器对象,并为每个处理器设置一个自定义的过滤器,这样就可以选择每个处理器要处理哪些日志记录。

撰写回答