Go 子进程通信

Posted

技术标签:

【中文标题】Go 子进程通信【英文标题】:Go subprocess communication 【发布时间】:2014-05-05 23:33:36 【问题描述】:

GO:有什么方法可以与等待 stdin 输入的子进程(shell 脚本/python 脚本)通信吗?

例如python脚本(子进程)

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

在 go 程序中,我想创建这个 python 脚本的子进程,并在必要时重复地在其标准输入上为其提供输入,并获取其输出。在 Go 程序的标准输出上写入或从文件中读取/写入也可以。

这大致是我正在尝试的,但没有任何反应 -

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 进程。 这就是为什么,你不应该忽略错误,尝试exec.Command("python", "-u", "add.py")exec.Command("python", "-u", "-i")exec.Command("python", "-i")(如果它不能使输出完全缓冲) 没有错误。还是不行 【参考方案1】:

这是您的 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"

【讨论】:

如果给循环添加延迟会发生什么?它是在最后一次打印结果还是一次打印结果?你需要si.Flush()si 是无缓冲的吗?在 Windows 上需要 \r\n 吗? @J.F.Sebastian 如果您添加延迟,它会正常工作 - 结果会慢慢出现。一切都是无缓冲的(除了上面的bufio),所以不需要刷新。 -u 负责 python 端。不确定 sys.stdin.readline() 是否会在 Windows 上读取 \n\r\n 但 go prog 只会发送并期待 \n

以上是关于Go 子进程通信的主要内容,如果未能解决你的问题,请参考以下文章

同一父进程下的子进程之间的通信(pipe通信)

子进程和父进程之间的通信

与子进程通信,无需等待子进程在 windows 上终止

swoole父进程和子进程之间通信的例子

swoole父进程和子进程之间通信的例子

Python中主进程和子进程之间的动态通信