如何用Python 3 logging按级别输出到stdout和stderr?
Python 3 logging 模块分级别输出到 stdout/stderr
要实现logging.debug()、logging.info()输出到stdout,logging.warning()、logging.error()输出到stderr,核心思路是给日志系统添加两个不同的StreamHandler,分别绑定到不同输出流,并通过过滤器或级别控制各自处理的日志等级。
方法一:基础实现(精准级别过滤)
直接为两个Handler配置对应输出流,并用过滤器限定处理的日志级别,同时确保根Logger能传递所有需要的日志:
import logging import sys # 设置根Logger级别为DEBUG,确保所有级别日志都能进入处理流程 logging.basicConfig(level=logging.DEBUG) # 创建绑定stdout的Handler,仅处理DEBUG和INFO级日志 stdout_handler = logging.StreamHandler(sys.stdout) stdout_handler.setLevel(logging.DEBUG) class StdoutFilter(logging.Filter): def filter(self, record): return record.levelno in (logging.DEBUG, logging.INFO) stdout_handler.addFilter(StdoutFilter()) # 创建绑定stderr的Handler,处理WARNING及以上级日志 stderr_handler = logging.StreamHandler(sys.stderr) stderr_handler.setLevel(logging.WARNING) # 移除basicConfig自动添加的默认Handler,避免重复输出 root_logger = logging.getLogger() for handler in root_logger.handlers[:]: root_logger.removeHandler(handler) # 为根Logger添加两个自定义Handler root_logger.addHandler(stdout_handler) root_logger.addHandler(stderr_handler) # 测试输出 logging.debug("这是debug日志,将输出到stdout") logging.info("这是info日志,将输出到stdout") logging.warning("这是warning日志,将输出到stderr") logging.error("这是error日志,将输出到stderr")
方法二:带自定义格式的进阶实现
如果需要为不同输出流设置差异化的日志格式,可以给每个Handler单独配置Formatter:
import logging import sys # 定义不同输出流的日志格式 stdout_formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(message)s') stderr_formatter = logging.Formatter('%(asctime)s | %(levelname)s | %(filename)s:%(lineno)d | %(message)s') # 配置stdout Handler stdout_handler = logging.StreamHandler(sys.stdout) stdout_handler.setLevel(logging.DEBUG) stdout_handler.setFormatter(stdout_formatter) class StdoutFilter(logging.Filter): def filter(self, record): return record.levelno <= logging.INFO # 覆盖DEBUG和INFO级别 stdout_handler.addFilter(StdoutFilter()) # 配置stderr Handler stderr_handler = logging.StreamHandler(sys.stderr) stderr_handler.setLevel(logging.WARNING) stderr_handler.setFormatter(stderr_formatter) # 初始化根Logger root_logger = logging.getLogger() root_logger.setLevel(logging.DEBUG) # 清理默认Handler for handler in root_logger.handlers[:]: root_logger.removeHandler(handler) root_logger.addHandler(stdout_handler) root_logger.addHandler(stderr_handler) # 测试 logging.debug("debug级信息,输出到stdout") logging.info("info级信息,输出到stdout") logging.warning("warning级信息,输出到stderr") logging.error("error级信息,输出到stderr")
关键注意点
- 必须移除
basicConfig自动生成的默认StreamHandler,否则会导致日志重复输出(默认Handler默认绑定stderr)。 - 根Logger的级别需设置为所需的最低级别(示例中为
DEBUG),否则低于该级别的日志会被直接拦截,无法传递到Handler。 - 使用
Filter可以更灵活地控制日志流向,相比单纯设置Handler级别,能精确指定特定级别或级别范围。
内容的提问来源于stack exchange,提问作者Justin
相关产品推荐
相关产品推荐

