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 子进程通信的主要内容,如果未能解决你的问题,请参考以下文章