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

使用Go的exec.Command通过管道读取数据时程序挂起问题

问题原因及解决方法

核心问题

程序挂起的主因是Python的输出缓冲机制:当Python的stdout不是终端(比如被Go的管道捕获)时,print默认采用块缓冲模式,不会立即将输出内容写入stdout管道,导致Go端的ReadLine()一直阻塞等待数据。

同时你的Go代码存在两处细节问题:

  • 未正确处理ReadLine()的返回值,直接打印buf(这是Reader对象,而非读取到的内容)
  • 写完stdin后未关闭管道,Python的for line in sys.stdin会持续等待更多输入(虽非本次挂起的主因,但会导致进程无法正常退出)

解决步骤

1. 修改Python脚本,强制刷新输出

给print添加flush=True参数,让输出立即写入管道:

import sys

if __name__=='__main__':
    for line in sys.stdin:
        print("Hello", line.strip(), flush=True)

也可以在print后手动调用刷新:

import sys

if __name__=='__main__':
    for line in sys.stdin:
        print("Hello", line.strip())
        sys.stdout.flush()

2. 修正Go代码的细节问题

处理ReadLine()的返回值,写完stdin后关闭管道(无需持续通信时),并等待命令执行完成避免僵尸进程:

package main

import (
    "bufio"
    "log"
    "os/exec"
)

func main() {
    cmd := exec.Command("python3", "app.py")
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        log.Fatal(err)
    }
    stdin, err := cmd.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }

    if err := cmd.Start(); err != nil {
        log.Fatal(err)
    }

    _, err = stdin.Write([]byte("Bob\n"))
    if err != nil {
        log.Fatal(err)
    }
    // 关闭stdin,告知Python输入结束
    if err := stdin.Close(); err != nil {
        log.Fatal(err)
    }

    buf := bufio.NewReader(stdout)
    line, _, err := buf.ReadLine()
    if err != nil {
        log.Fatal(err)
    }
    log.Println(string(line))

    // 等待命令执行完成
    if err := cmd.Wait(); err != nil {
        log.Fatal(err)
    }
}

额外说明

若需要和Python程序保持持续双向通信,不要关闭stdin,但需确保Python端每次输出都主动刷新,同时Go端要实现循环读写的逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 10:15:20