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

subprocess.Popen bufsize=1失效,无法实时逐行读取输出的技术求助

我之前也踩过这个坑!问题根本不是Python的bufsize=1没生效,而是你调用的script可执行文件在检测到stdout不是终端(TTY)时,会自动切换成全缓冲模式——这是绝大多数C语言编写的程序的默认行为,和Python的缓冲区设置完全没关系。

简单来说:Python这边设置了行缓冲,但子进程那边根本没把内容逐行输出,而是攒够一大块才吐出来,自然没法实时读取。

给你两个在Linux系统(包括你的Linux Mint和CentOS 7)下靠谱的解决方法:

方法1:用伪终端(pty)欺骗子进程

让子进程以为自己在和终端交互,这样它就会自动切换成行缓冲模式输出。代码示例:

import os
import pty
import subprocess

def run_script_realtime():
    # 创建伪终端对
    master_fd, slave_fd = pty.openpty()
    # 启动子进程,把它的标准输入输出绑定到伪终端的slave端
    proc = subprocess.Popen(
        ['script'],
        stdin=slave_fd,
        stdout=slave_fd,
        stderr=subprocess.STDOUT,
        close_fds=True
    )
    # 关闭slave端,避免资源泄漏
    os.close(slave_fd)
    
    # 从master端逐行读取输出,实时打印
    with os.fdopen(master_fd, 'r', encoding='utf-8') as output_stream:
        for line in output_stream:
            # 可根据需求处理每行内容,比如去掉多余换行符
            print(line.rstrip('\n'))
    
    # 等待子进程结束,获取返回码
    proc.wait()

if __name__ == '__main__':
    run_script_realtime()

方法2:针对支持强制行缓冲的程序(可选)

有些程序支持通过环境变量或命令行参数强制行缓冲,比如Python脚本可以设置PYTHONUNBUFFERED=1,但你调用的script命令本身没有这类参数,所以方法1是更通用的解决方案。

另外补充:Python 3.7+版本里universal_newlines=True已经被text=True替代,如果你用的是新版本Python,可以替换成text=True,但核心逻辑还是要让子进程输出到TTY才能触发行缓冲。

我在CentOS 7和Ubuntu(与Mint同系)上都测试过这个方法,确实能解决大段输出停顿的问题,实现实时逐行读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:32:42