繁体   English   中英

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

[英]Running external python in Golang, Catching continuous exec.Command Stdout

所以我的 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脚本会无限运行,并且会不时打印出一些信息。 我想“捕捉”这些标准输出并在我的 golang 终端上打印出来。 如何同时执行(无需等待我的 python 脚本退出)?

使用cmd.Start()cmd.Wait()而不是cmd.Run()

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

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

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

Wait 等待命令退出。 它必须由 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 代码。 标准输出可以在 Python 中缓冲。 可能需要显式刷新。

import time
import sys

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

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

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

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

https://bugs.python.org/issue526382

如果要同时捕获 stdout 和 stderr,确实需要使用cmd.StdoutPipe()cmd.StderrPipe()cmd.Start()cmd.Wait()

但如文档中所述( https://pkg.go.dev/os/exec#Cmd.StdoutPipe ):

因此,在管道的所有读取完成之前调用 Wait 是不正确的。

在调用cmd.Wait()之前,您需要等待 goroutine 完成(请参阅以下线程: https ://github.com/golang/go/issues/38268)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM