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

使用subprocess.Popen导致Ubuntu终端输出混乱的问题求助

解决subprocess.Popen终端输出混乱问题

终端输出错乱的核心原因是:Python主进程和agt_internal子进程同时往标准输出(终端)写入内容,两个进程的输出互相抢占,导致内容交织错乱。以下是几种可行的解决方案:

方案1:将子进程输出重定向到文件

如果不需要在终端看到子进程的输出,可以直接把它的标准输出和错误输出写到文件里,彻底避免和主进程的print冲突:

import subprocess
import time

def start_agt_pmlog():
    command = 'sudo ./agt_internal -unilog=PM'
    args = command.split()  # 或用shlex.split,效果一致
    print('Starts AGT PMLog')
    # 打开日志文件,以追加模式写入
    with open('/home/boblittle/AGT/agt_log.txt', 'a') as log_file:
        subprocess.Popen(
            args,
            shell=False,
            cwd="/home/boblittle/AGT/",
            stdout=log_file,
            stderr=log_file  # 把错误输出也写到同一个文件
        )

start_agt_pmlog()
time.sleep(10)

for i in range(10):
    print('Good Morning America')

方案2:实时读取子进程输出并统一处理

如果需要在终端看到子进程的输出,同时避免错乱,可以用线程单独读取子进程的输出流,给子进程的输出加上标识(比如[AGT]),确保输出区分开:

import subprocess
import time
import threading

def read_subprocess_output(stream, prefix):
    # 逐行读取子进程输出并打印
    for line in iter(stream.readline, b''):
        print(f'{prefix} {line.decode().strip()}')

def start_agt_pmlog():
    command = 'sudo ./agt_internal -unilog=PM'
    args = command.split()
    print('Starts AGT PMLog')
    proc = subprocess.Popen(
        args,
        shell=False,
        cwd="/home/boblittle/AGT/",
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True  # 直接以文本模式读取,不用手动decode
    )
    # 启动两个线程分别处理stdout和stderr
    threading.Thread(target=read_subprocess_output, args=(proc.stdout, '[AGT_OUT]'), daemon=True).start()
    threading.Thread(target=read_subprocess_output, args=(proc.stderr, '[AGT_ERR]'), daemon=True).start()
    return proc

start_agt_pmlog()
time.sleep(10)

for i in range(10):
    print('Good Morning America')

注:设置daemon=True是让线程随主进程退出而结束,避免主进程退出后线程残留。

方案3:等待子进程执行完毕再运行主进程输出

如果不需要子进程在后台运行,可以用subprocess.run替代Popen,等待子进程执行完成后再执行主进程的print:

import subprocess
import time

def start_agt_pmlog():
    command = 'sudo ./agt_internal -unilog=PM'
    args = command.split()
    print('Starts AGT PMLog')
    # run会等待子进程执行完毕
    subprocess.run(
        args,
        shell=False,
        cwd="/home/boblittle/AGT/",
        # 如果需要看子进程输出,去掉下面两行;否则重定向到/dev/null
        stdout=subprocess.DEVNULL,
        stderr=subprocess.DEVNULL
    )

start_agt_pmlog()
time.sleep(10)

for i in range(10):
    print('Good Morning America')

为什么你之前的修改没解决问题?

你之前用了stdout=subprocess.PIPE和stderr=subprocess.PIPE,但没有读取管道中的内容:

  • 子进程的输出会被暂存在管道缓冲区,当缓冲区满时子进程会被阻塞,无法正常运行;
  • 而且这种方式并没有解决主进程和子进程同时写终端的问题,只是把子进程的输出暂时存起来了,一旦读取管道内容并打印,还是会和主进程的print交织。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 14:45:28