Search code examples
pythongosubprocessstdininter-process-communicat

Go subprocess communication


GO: Is there some way to communicate with a subprocess (shell script / python script), which is waiting for input on stdin?

e.g. python script (subprocess)

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

In the go program, I want to create a subprocess of this python script and provide it input on its stdin, whenever necessary and repeatedly, and take its output. Writing on stdout of Go program or reading/writing from a file will also do.

This is roughly what I am trying, but nothing happens -

c := exec.Command("python", "-u add.py")
si,_ := c.StdinPipe()
so,_ := c.StdoutPipe()    
c.Start()
si.Write([]byte("2+2\n")

Solution

  • Here is a working version of your go code (python code is unchanged).

    Note: checking of all errors, fixed -u flag, use of bufio to read a line, and Wait to wait for end of process.

    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()
    }
    

    Which produces

    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"