日志logging,StreamHandler和标准stream

我无法弄清楚如何将信息级别的消息logging到标准输出,但是其他的一切都是标准input。 我已经阅读这个http://docs.python.org/library/logging.html 。 任何build议?

以下脚本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
一个DEBUG消息
 INFO消息
警告消息
一个错误消息
关键信息

正如你所期望的,因为在一个terminal上sys.stdoutsys.stderr是一样的。 现在,让我们将stdoutredirect到文件tmp

 C:\ temp> log1.py> tmp
一个DEBUG消息
警告消息
一个错误消息
关键信息

所以INFO消息没有被打印到terminal – 但是发送到sys.stderr的消息已经被打印了。 让我们来看看tmp

 C:\ temp>键入tmp
 INFO消息

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

通常情况下,我认为WARNING消息redirect到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 #... 

由于我的编辑被拒绝,这是我的答案。 @ 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")