Go子进程通信

7

GO: 有没有一种方式可以与等待stdin输入的子进程(shell脚本/Python脚本)进行通信?

例如:Python脚本(子进程)

import sys
while True:
    sys.stdout.write('%s\n'%eval(sys.stdin.readline()))

在go程序中,我想创建这个python脚本的子进程,并在必要时反复提供其stdin输入,并获取其输出。可以写入Go程序的stdout或从文件读取/写入也可以。
这大致是我正在尝试的,但什么也没有发生-
c := exec.Command("python", "-u add.py")
si,_ := c.StdinPipe()
so,_ := c.StdoutPipe()    
c.Start()
si.Write([]byte("2+2\n")

与编程有关的内容翻译如下:无关紧要:您可以将Python 2中的eval(sys.stdin.readline())替换为input()。或者使用import code; shell = code.InteractiveConsole(); shell.interact()替换整个循环。或者只需启动python -i进程即可。 - jfs
这就是为什么你不应该忽略错误,尝试使用 exec.Command("python", "-u", "add.py") 或者 exec.Command("python", "-u", "-i") 或者 exec.Command("python", "-i")(如果它不能使输出完全缓冲)。 - jfs
仍然无法工作。 - Palash Kumar
1个回答

5
这是一个工作版本的Go代码(Python代码未更改)。
请注意:检查所有错误,修复-u标志,使用bufio读取一行,并使用Wait等待进程结束。
import (
    "bufio"
    "fmt"
    "log"
    "os/exec"
)

func main() {
    c := exec.Command("python", "-u", "add.py")
    si, err := c.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }

    so, err := c.StdoutPipe()
    if err != nil {
        log.Fatal(err)
    }
    reader := bufio.NewReader(so)

    err = c.Start()
    if err != nil {
        log.Fatal(err)
    }

    // Now do some maths
    for i := 0; i < 10; i++ {
        sum := fmt.Sprintf("2+%d\n", i)
        _, err = si.Write([]byte(sum))
        if err != nil {
            log.Fatal(err)
        }
        answer, err := reader.ReadString('\n')
        if err != nil {
            log.Fatal(err)
        }
        fmt.Printf("Answer to %q is %q\n", sum, answer)
    }

    // Close the input and wait for exit
    si.Close()
    so.Close()
    c.Wait()
}

这将产生

Answer to "2+0\n" is "2\n"
Answer to "2+1\n" is "3\n"
Answer to "2+2\n" is "4\n"
Answer to "2+3\n" is "5\n"
Answer to "2+4\n" is "6\n"
Answer to "2+5\n" is "7\n"
Answer to "2+6\n" is "8\n"
Answer to "2+7\n" is "9\n"
Answer to "2+8\n" is "10\n"
Answer to "2+9\n" is "11\n"

1
如果在循环中添加延迟,会发生什么?它会一个接一个地打印结果还是一次性在结尾处打印所有结果?你需要 si.Flush() 还是 si 是无缓冲的?在 Windows 上需要 \r\n 吗? - jfs
1
@J.F.Sebastian 如果你添加一个延迟,它就可以正常工作了——结果会逐个缓慢出现。在 Go 中,除了上面的 bufio 之外,一切都是无缓冲的,因此不需要刷新。-u 处理了 Python 端。不确定 sys.stdin.readline() 在 Windows 上是否会读取 \n 还是 \r\n,但 Go 程序只会发送和期望 \n - Nick Craig-Wood

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接