在Golang中运行外部python,捕获连续的exec.Command Stdout

时间:2017-01-01 12:09:48

标签: go

所以我的go脚本将调用这样的外部python

cmd = exec.Command("python","game.py")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
go func(){
    err := cmd.Run()
    if err != nil{
    panic(err)
    }
}()

它同时运行我的python脚本,这很棒。 但现在问题是,我的python脚本将无限运行,它会不时打印出一些信息。我想“抓住”这些Stdout并在golang终端上打印出来。我如何同时进行(不等待我的python脚本退出)?

2 个答案:

答案 0 :(得分:4)

使用cmd.Start()cmd.Wait()代替cmd.Run()

https://golang.org/pkg/os/exec/#Cmd.Run

  

运行启动指定的命令并等待它完成。

     

开始启动指定的命令,但不等待它完成。

     

等待命令退出。它必须由Start开始。

如果您想同时捕获stdout / stderr,请使用cmd.StdoutPipe() / cmd.StderrPipe()并按bufio.NewScanner()

阅读
package main

import (
    "bufio"
    "fmt"
    "io"
    "os/exec"
)

func main() {
    cmd := exec.Command("python", "game.py")
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        panic(err)
    }
    stderr, err := cmd.StderrPipe()
    if err != nil {
        panic(err)
    }
    err = cmd.Start()
    if err != nil {
        panic(err)
    }

    go copyOutput(stdout)
    go copyOutput(stderr)
    cmd.Wait()
}

func copyOutput(r io.Reader) {
    scanner := bufio.NewScanner(r)
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
}

以下是用于再现实时输出的示例python代码。 stdout可以在Python中缓冲。可能需要明确刷新。

import time
import sys

while True:
    print "Hello"
    sys.stdout.flush()
    time.sleep(1)

答案 1 :(得分:1)

您可以使用添加标志 -u 来关闭缓冲,

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

https://docs.python.org/3/using/cmdline.html#cmdoption-u

https://bugs.python.org/issue526382