在 "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
之间存在差异,如何解决?
更多诊断信息:
- 当从
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
或 运行 Python 无缓冲标准输出和标准错误:
cmd := exec.Command("python", "-u", "foo.py")
注意 -u 标志。
使用 cmd.Stout = os.Stdout
时您会看到不同的结果,因为当 stdout 是终端时 Python 使用行缓冲。
这个问题与 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
或 运行 Python 无缓冲标准输出和标准错误:
cmd := exec.Command("python", "-u", "foo.py")
注意 -u 标志。
使用 cmd.Stout = os.Stdout
时您会看到不同的结果,因为当 stdout 是终端时 Python 使用行缓冲。