Go 正在从“exec.Cmd`in”获取输出;“实时”;
这个问题与类似,只是它与Go 正在从“exec.Cmd`in”获取输出;“实时”;,go,exec,stdout,buffering,Go,Exec,Stdout,Buffering,这个问题与类似,只是它与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 {
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之间存在差异?如何解决
更多诊断信息:
- 从
中删除循环时,两个程序都会输出“hello”,正如预期的那样inf\u loop.py
- 当使用
作为程序而不是python脚本,并在yes
outstream.Write中输出
时,就会有输出,输出通常是16384或32768。这向我表明,正如我最初预期的那样,这是一个缓冲问题,但我仍然不理解为什么len(p)
结构被缓冲阻止,而outstream
没有。一种可能性是,该行为是os.Stdout
将exec
直接传递到io.Writer
的方式的结果,如果它是os.StartProcess
(请参阅以获取详细信息),否则它会在进程和os.File
之间创建一个io.Writer
os.Pipe(),这条管道可能会导致缓冲。但是,
的操作和可能的缓冲级别太低,我无法进行调查os.Pipe()
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使用行缓冲。完美的答案,谢谢!仅供将来参考,我很好奇Python是如何知道在后一种情况下stdout是一个终端的,并发现一般的方法是使用。顺便说一句,Linux(实际上是GNU coreutils)和FreeBSD(可能还有其他)有stdbuf
,它改变了任意命令的初始缓冲。对于没有选项的命令(如此处显示的-u
,或grep的--line buffered
)非常有用。