You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python日志:如何避免stderr与stdout中日志信息重复输出

日志分级输出去重解决方案

我需要将INFO、WARNING级别日志输出到stdout,ERROR及以上级别输出到stderr,但当前配置下ERROR日志同时出现在stdout和stderr中,出现重复。以下是代码、配置及输出情况:

代码实现

import os
import subprocess
from typing import Union
import logging
import yaml
import logging.config

with open("logging.conf", "r") as f:
    config = yaml.safe_load(f.read())
    logging.config.dictConfig(config)


logger = logging.getLogger(__name__)    


def run(
    cmd: Union[str, list[str]],
    *,
    cwd: Union[str, os.PathLike[str], None] = None,
    shell: bool = False,
    check: bool = True,
    capture_output: bool = True,
    text: bool = True,
) -> subprocess.CompletedProcess[str]:
    logger.info("start run!!")
    return subprocess.run(cmd, check=True, capture_output=capture_output, text=text)


cmd = ["lxs"]


def main():
    try:
        output = run(cmd)
    except Exception as e:
        logger.error(e, exc_info=False)


main()

原日志配置(logging.conf)

version: 1
formatters:
  simple:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
handlers:
  outconsole:
    class: logging.StreamHandler
    level: INFO
    formatter: simple
    stream: ext://sys.stdout
  errconsole:
    class: logging.StreamHandler
    level: WARNING
    formatter: simple
    stream: ext://sys.stderr

  file_handler:
    class: logging.FileHandler
    level: INFO
    formatter: simple
    filename: info.log
    encoding: utf8
    mode: w

loggers:
  sampleLogger:
    level: DEBUG
    handlers: [file_handler]
    propagate: no
root:
  level: INFO
  handlers: [errconsole, outconsole, file_handler]
  propagate: no

原执行结果

执行命令:python3 -m tests 1> output.log 2> err.log

  • err.log内容:
2022-10-14 14:34:02,354 - __main__ - ERROR - [Errno 2] No such file or directory: 'lxs'
  • output.log内容:
2022-10-14 14:34:02,353 - __main__ - INFO - start run!!
2022-10-14 14:34:02,354 - __main__ - ERROR - [Errno 2] No such file or directory: 'lxs'
  • 控制台输出:
2022-10-14 14:48:33,178 - __main__ - INFO - start run!!
2022-10-14 14:48:33,179 - __main__ - ERROR - [Errno 2] No such file or directory: 'lxs'
2022-10-14 14:48:33,179 - __main__ - ERROR - [Errno 2] No such file or directory: 'lxs'

问题原因

当前配置中,outconsole handler的级别设为INFO,ERROR级别高于INFO,因此ERROR日志会被outconsole捕获输出;同时errconsole的级别是WARNING,ERROR也满足该级别条件,导致两个handler都输出ERROR日志,出现重复。

解决方法

通过添加日志过滤器,限制outconsole仅处理INFO和WARNING级别日志,拒绝ERROR及以上级别日志,同时调整errconsole的级别为ERROR,精准捕获目标日志。

1. 修改代码添加过滤器类

在导入logging模块后添加自定义过滤器:

class InfoWarningFilter(logging.Filter):
    def filter(self, record):
        # 只保留INFO和WARNING级别的日志
        return record.levelno in (logging.INFO, logging.WARNING)

2. 更新logging.conf配置

version: 1
formatters:
  simple:
    format: '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
filters:
  info_warning_only:
    (): __main__.InfoWarningFilter  # 引用自定义过滤器类
handlers:
  outconsole:
    class: logging.StreamHandler
    level: INFO
    formatter: simple
    stream: ext://sys.stdout
    filters: [info_warning_only]  # 绑定过滤器
  errconsole:
    class: logging.StreamHandler
    level: ERROR  # 调整为ERROR,仅捕获ERROR及以上级别
    formatter: simple
    stream: ext://sys.stderr

  file_handler:
    class: logging.FileHandler
    level: INFO
    formatter: simple
    filename: info.log
    encoding: utf8
    mode: w

loggers:
  sampleLogger:
    level: DEBUG
    handlers: [file_handler]
    propagate: no
root:
  level: INFO
  handlers: [errconsole, outconsole, file_handler]
  propagate: no

验证修改后效果

重新执行命令python3 -m tests 1> output.log 2> err.log:

  • output.log仅包含INFO和WARNING日志:
2022-10-14 14:34:02,353 - __main__ - INFO - start run!!
  • err.log仅包含ERROR及以上日志:
2022-10-14 14:34:02,354 - __main__ - ERROR - [Errno 2] No such file or directory: 'lxs'
  • 控制台输出不再出现重复的ERROR日志。

内容的提问来源于stack exchange,提问作者MattyOstrowsky

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 19:50:22