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

Python subprocess未写入预期输出问题排查

问题:subprocess日志文件仅写入<_io.TextIOWrapper...>而非预期运行日志

我编写了一段Python脚本代码,可正常生成任务输出文件且无报错,但subprocess的stdout日志文件(如COSMOSIS_output_XXX.txt)未存储预期的运行日志,仅写入<_io.TextIOWrapper name=9 encoding='UTF-8'>内容,请问我哪里出错了?

import subprocess
from subprocess import Popen
jobname = "cosmosis"
arg2 = "output.filename="
Vector = (
    " " + ini + " " + arg2 + COSMOSIS_PATH + os.path.splitext(ini)[0] + ".txt"
)                                                                                                                                                                                               

job3 = subprocess.Popen(
    ["cosmosis" + Vector],
    shell=True,
    text=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
)

file = open("%sCOSMOSIS_output_%s.txt" % (ERROR_PATH, ini), "a")
sys.stdout = file
print(job3.stdout)
file_e = open("%sCOSMOSIS_output_ERROR_%s.txt" % (ERROR_PATH, ini), "a")
sys.stdout = file_e
print(job3.stderr)
try:
    outs, errs = job3.communicate(timeout=2000)                                                                                                                                      
except TimeoutExpired:
    outs, errs = job3.communicate()
    job3.kill()
file.close()
file_e.close()
问题分析与修复方案

核心错误点

  1. 直接打印管道对象而非读取输出内容
    你当前print(job3.stdout)打印的是subprocess的管道对象本身,不是管道里的实际运行日志,所以文件里才会出现<_io.TextIOWrapper...>这种对象描述文本,而非预期的日志内容。

  2. 错误的sys.stdout重定向逻辑
    修改sys.stdout来写入日志是完全没必要的操作,既打乱了标准输出的正常流向,又没解决读取子进程输出的核心问题。

  3. subprocess调用的参数冗余
    使用shell=True时,传入["cosmosis" + Vector]这种单元素列表属于冗余写法,直接传入拼接好的命令字符串即可。

修正后的代码

import subprocess
from subprocess import Popen, TimeoutExpired
import os
import sys

jobname = "cosmosis"
arg2 = "output.filename="
Vector = (
    " " + ini + " " + arg2 + COSMOSIS_PATH + os.path.splitext(ini)[0] + ".txt"
)

# 优化shell=True时的命令传参方式
job3 = subprocess.Popen(
    "cosmosis" + Vector,
    shell=True,
    text=True,
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
)

try:
    # 先获取子进程的真实输出和错误内容
    outs, errs = job3.communicate(timeout=2000)
except TimeoutExpired:
    job3.kill()
    outs, errs = job3.communicate()

# 直接将获取到的内容写入对应文件,用with语句自动管理文件生命周期
with open(f"{ERROR_PATH}COSMOSIS_output_{ini}.txt", "a") as file:
    file.write(outs)

with open(f"{ERROR_PATH}COSMOSIS_output_ERROR_{ini}.txt", "a") as file_e:
    file_e.write(errs)

关键修正说明

  • 先通过communicate()读取子进程的真实输出和错误内容,而非直接操作管道对象
  • 移除了不必要的sys.stdout重定向,直接写入获取到的日志内容
  • 使用with语句自动处理文件打开/关闭,避免手动关闭可能出现的异常
  • 调整超时处理顺序,先终止进程再获取剩余输出,逻辑更合理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 00:55:21