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

Python调用含read交互的Bash脚本:实时输出与高效捕获优化

高效运行交互式Bash脚本的Python实现

核心思路

  • 采用非阻塞批量读取子进程输出,减少IO调用次数提升效率
  • 监控子进程状态,当检测到子进程阻塞等待输入时,立即flush已读取的所有输出,确保提示完整显示
  • 读取用户输入后传递给子进程,继续执行

代码实现

import subprocess
import fcntl
import os
import sys

def run_interactive_script(script_path):
    # 启动子进程,绑定标准输入输出
    proc = subprocess.Popen(
        ['bash', script_path],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,  # 合并stderr到stdout统一处理
        text=True
    )

    # 设置stdout为非阻塞模式
    fd = proc.stdout.fileno()
    fl = fcntl.fcntl(fd, fcntl.F_GETFL)
    fcntl.fcntl(fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)

    captured_output = []
    buffer = []

    while proc.poll() is None:
        try:
            # 批量读取数据块(默认4096字节,可根据需求调整)
            chunk = proc.stdout.read(4096)
            if chunk:
                buffer.append(chunk)
                sys.stdout.write(chunk)
                sys.stdout.flush()
                captured_output.append(chunk)
            else:
                # 无数据可读,判定子进程等待输入
                if buffer:
                    sys.stdout.flush()
                    buffer = []
                # 读取用户输入并传递给子进程
                user_input = input() + '\n'
                proc.stdin.write(user_input)
                proc.stdin.flush()
        except BlockingIOError:
            # 非阻塞读取无数据,继续循环检测子进程状态
            continue
        except Exception as e:
            print(f"Error: {e}", file=sys.stderr)
            break

    # 读取子进程剩余输出
    remaining = proc.stdout.read()
    if remaining:
        sys.stdout.write(remaining)
        sys.stdout.flush()
        captured_output.append(remaining)

    return ''.join(captured_output), proc.returncode

# 示例调用
if __name__ == "__main__":
    output, code = run_interactive_script("test.sh")
    print(f"\n脚本执行完成,返回码:{code}")
    print(f"捕获的全部输出:\n{output}")

关键细节说明

  • 非阻塞读取:通过fcntl修改子进程stdout的文件描述符属性,避免批量读取时阻塞等待数据
  • 批量读取:每次读取4096字节的块,大幅减少IO操作次数,彻底解决逐字符读取的性能瓶颈
  • 无依赖兼容:无需修改目标Bash脚本,也不依赖任何已知提示内容,适用于所有交互式Bash场景
  • 实时输出保障:每次读取到数据块立即输出并flush,子进程等待输入前确保所有提示内容已显示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 01:48:09