这个问题类似于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
之间存在差异,如何解决?
一些更多的诊断信息:
- 当循环从
inf_loop.py
中移除时,两个程序都会输出“hello”,正如预期的那样。 - 当使用
yes
作为程序而不是 python 脚本并在outstream.Write
中输出len(p)
时,就会有输出,并且输出通常是 16384 或 32768。这向我表明这是一个缓冲问题,正如我最初预期的那样,但我仍然不明白为什么outstream
结构被缓冲阻塞但是os.Stdout
不是。一种可能是该行为是exec
将io.Writer
直接传递给os.StartProcess
的方式的结果,如果它是os.File
(详见 source),否则它会在进程和io.Writer
之间创建一个os.Pipe()
,并且此管道可能导致缓冲。但是,os.Pipe()
的操作和可能的缓冲级别太低,我无法研究。
最佳答案
Python 默认缓冲标准输出。试试这个程序:
import sys
print "hello"
sys.stdout.flush()
while True:
pass
或者使用无缓冲的 stdout 和 stderr 运行 Python:
cmd := exec.Command("python", "-u", "foo.py")
注意 -u 标志。
当使用 cmd.Stout = os.Stdout
时,您会看到不同的结果,因为当 stdout 是终端时,Python 使用行缓冲。
关于go - 从 `exec.Cmd` 中获取 "real-time"的输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31015754/