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

调用subprocess执行脚本时,logging输出与异常捕获问题求助

问题解决指南

问题1:logging输出全部流入stderr

原因

Python的logging模块默认使用StreamHandler,且默认指向sys.stderr,所有级别(INFO、WARNING、ERROR)的日志都会输出到stderr。

解决方案

在b.py中配置两个日志处理器,分别将不同级别的日志导向stdout和stderr:

import logging
import sys

# 处理INFO和WARNING级别的日志,输出到stdout
stdout_handler = logging.StreamHandler(sys.stdout)
stdout_handler.setLevel(logging.INFO)
# 过滤掉ERROR及以上级别的日志
stdout_handler.addFilter(lambda record: record.levelno < logging.ERROR)

# 处理ERROR及以上级别的日志,输出到stderr
stderr_handler = logging.StreamHandler(sys.stderr)
stderr_handler.setLevel(logging.ERROR)

# 配置根logger
root_logger = logging.getLogger()
root_logger.setLevel(logging.INFO)  # 确保INFO及以上级别被捕获
root_logger.addHandler(stdout_handler)
root_logger.addHandler(stderr_handler)

问题2:a.py无法捕获b.py的执行错误

原因

subprocess.Popen和communicate()仅在启动子进程失败时(比如找不到Python解释器、b.py不存在)才会抛出异常。如果b.py运行过程中出错(比如代码抛出异常),子进程只会返回非零的返回码,不会触发a.py的except块。

解决方案

方案1:检查返回码手动抛出异常

修改a.py的代码,在communicate()后检查子进程的返回码,非零则手动触发异常:

import subprocess as sp
import json

# 假设user_conf已定义
user_conf = {"key": "value"}

try:
    p = sp.Popen(
           ["python", "b.py", "--user_config", json.dumps(user_conf)],
           stdin=sp.PIPE,
           stdout=sp.PIPE,
           stderr=sp.PIPE,
           encoding='cp1252'
        )

    stdout, stderr = p.communicate()
    
    # 检查返回码,非零表示子进程执行出错
    if p.returncode != 0:
        raise RuntimeError(f"b.py执行失败,返回码:{p.returncode},错误信息:{stderr}")

except Exception as e:
    print(e)

else:
    print("Script continues...")

方案2:使用subprocess.run简化处理

subprocess.run支持check=True参数,当子进程返回非零码时自动抛出CalledProcessError异常,代码更简洁:

import subprocess as sp
import json

user_conf = {"key": "value"}

try:
    result = sp.run(
        ["python", "b.py", "--user_config", json.dumps(user_conf)],
        stdin=sp.PIPE,
        stdout=sp.PIPE,
        stderr=sp.PIPE,
        encoding='cp1252',
        check=True
    )
    # 正常执行时获取输出
    print("b.py stdout:", result.stdout)
except sp.CalledProcessError as e:
    print(f"b.py执行出错:{e.stderr}")
except Exception as e:
    print(e)
else:
    print("Script continues...")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 05:15:33