"""子进程运行并把 stdout/stderr 合并;可选将逐行输出写入 loguru(测量/行为推理可关闭以减少日志)。""" from __future__ import annotations import os import subprocess from typing import Dict, List, Optional from loguru import logger def run_subprocess_with_log( cmd: List[str], *, cwd: str, env: Optional[Dict[str, str]] = None, log_name: str, stream_to_logger: bool = True, ) -> subprocess.CompletedProcess[str]: """运行子进程,合并 stderr 到 stdout,可选按行输出到 loguru。 返回 CompletedProcess,stdout 为完整输出,便于失败时拼进异常信息。 ``stream_to_logger=False`` 时不把子进程逐行写入日志(仍完整收集 stdout)。 """ proc = subprocess.Popen( cmd, cwd=cwd, env=env if env is not None else os.environ.copy(), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1, ) lines: List[str] = [] if proc.stdout is not None: for line in proc.stdout: lines.append(line) if stream_to_logger: s = line.rstrip() if s: logger.info("[{}] {}", log_name, s) rc = proc.wait() out = "".join(lines) return subprocess.CompletedProcess(cmd, rc, out, "")