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")
Popen is more general than subprocess. call . Popen doesn't block, allowing you to interact with the process while it's running, or continue with other things in your Python program. The call to Popen returns a Popen object.
popen. To run a process and read all of its output, set the stdout value to PIPE and call communicate(). The above script will wait for the process to complete and then it will display the output.
Popen is nonblocking. call and check_call are blocking. You can make the Popen instance block by calling its wait or communicate method.
Popen Function The function should return a pointer to a stream that may be used to read from or write to the pipe while also creating a pipe between the calling application and the executed command. Immediately after starting, the Popen function returns data, and it does not wait for the subprocess to finish.
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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With