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()
问题分析与修复方案
核心错误点
直接打印管道对象而非读取输出内容
你当前print(job3.stdout)打印的是subprocess的管道对象本身,不是管道里的实际运行日志,所以文件里才会出现<_io.TextIOWrapper...>这种对象描述文本,而非预期的日志内容。错误的sys.stdout重定向逻辑
修改sys.stdout来写入日志是完全没必要的操作,既打乱了标准输出的正常流向,又没解决读取子进程输出的核心问题。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
相关产品推荐
相关产品推荐

