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

如何用subprocess模块监控无换行持续输出的Python脚本

实时监控Python脚本的无换行更新输出

问题场景

需要并行运行并实时监控一个Python脚本的输出,但该脚本通过\r(回车符)更新当前行内容,没有输出换行符,常规的subprocess读取方法(如readline()、read()、communicate())均无法正常获取实时输出。

目标脚本(noNewLine1.py)

import time
i=0
print("Starting")
while True:
    time.sleep(1)
    print("Running {: 5d}".format(i), end="\r")
    i+=1
print()

在Shell中运行时,第二行会每秒更新一次数字,不会产生新行。

无效的初始尝试

import subprocess
import time

a = subprocess.Popen(["python3", "noNewLine1.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while True :
    time.sleep(1)
    # b = a.stdout.readline() # 挂起,因为没有换行符触发行读取
    # b = a.stdout.read(1)    # 同样挂起,因为stdout默认缓冲未刷新
    b = a.communicate(timeout=1) # 超时,无法获取实时输出
    print(b)

解决方案

方法1:禁用目标脚本的输出缓冲

Python默认会对stdout进行缓冲,当输出没有换行符时,内容会留在缓冲区中,不会发送到管道。可以通过两种方式禁用缓冲:

方式A:修改目标脚本的print语句

在print时添加flush=True强制刷新缓冲区:

import time
i=0
print("Starting")
while True:
    time.sleep(1)
    print("Running {: 5d}".format(i), end="\r", flush=True)
    i+=1
print()

方式B:启动Python时使用-u参数

无需修改目标脚本,在启动子进程时添加-u参数(禁用缓冲):

import subprocess
import time

# 使用-u参数禁用目标脚本的stdout缓冲
a = subprocess.Popen(
    ["python3", "-u", "noNewLine1.py"],
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,
    text=True  # 直接读取字符串而非字节流
)

while True:
    # 读取输出,此时即使没有换行也能获取到内容
    chunk = a.stdout.readline()
    if chunk:
        # 处理回车符,避免输出混乱
        print(chunk.strip('\r'), end='\r')
    # 检查子进程是否已终止
    if a.poll() is not None:
        break
    time.sleep(0.1)

方法2:模拟终端环境(无需修改目标脚本)

如果无法修改目标脚本,可以用pty模块模拟终端,因为Python在终端环境下会使用行缓冲而非全缓冲,输出会实时刷新:

import pty
import os
import subprocess

# 创建伪终端
master, slave = pty.openpty()
# 将子进程的输出绑定到伪终端的slave端
a = subprocess.Popen(
    ["python3", "noNewLine1.py"],
    stdout=slave,
    stderr=slave,
    text=True
)
os.close(slave)

while True:
    try:
        # 从主端读取输出
        output = os.read(master, 1024)
        if not output:
            break
        # 将回车符替换为换行,方便查看历史输出
        print(output.replace('\r', '\n'), end='')
    except OSError:
        # 子进程终止后会触发OSError,退出循环
        break
a.wait()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 10:28:37