在 "real-time" 中从 `exec.Cmd` 获取输出

Getting output from `exec.Cmd` in "real-time"

这个问题与 Golang - Copy Exec output to Log 类似,只是它与 exec 命令输出的缓冲有关。

我有以下测试程序:

package main

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

func main() {
    cmd := exec.Command("python", "inf_loop.py")
    var out outstream
    cmd.Stdout = out
    if err := cmd.Start(); err != nil {
        log.Fatal(err)
    }
    fmt.Println(cmd.Wait())
}

type outstream struct{}

func (out outstream) Write(p []byte) (int, error) {
    fmt.Println(string(p))
    return len(p), nil
}
上面提到的

inf_loop.py,简单的包含:

print "hello"
while True:
    pass

go 程序在我 运行 时挂起并且不输出任何内容,但是如果我使用 os.Stdout 而不是 out 那么它会在它之前输出 "hello"挂起。为什么两个 io.Writer 之间存在差异,如何解决?

更多诊断信息:

Python 默认缓冲标准输出。试试这个程序:

import sys
print "hello"
sys.stdout.flush()
while True:
    pass

或 运行 Python 无缓冲标准输出和标准错误:

cmd := exec.Command("python", "-u", "foo.py")

注意 -u 标志。

使用 cmd.Stout = os.Stdout 时您会看到不同的结果,因为当 stdout 是终端时 Python 使用行缓冲。