0

I am trying to run a exec.Command python.exe to run the python shell interactively. How can I type into it?

package main

import (
    "fmt"
    "os"
    "os/exec"
    "io"
    "log"
)

func main() {
    
    fmt.Println("Before Python shell:")
    
    cmd := exec.Command("python.exe")
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    _ = cmd.Run()
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
Gary
  • 2,293
  • 2
  • 25
  • 47
  • 1
    You can prompt for input from golang, then pass that along to `python -c "python expression"`, and have that be evaluated. Otherwise, call `python script.py`, but I don't think you'll get anything more than that – OneCricketeer Apr 22 '23 at 13:40
  • yes. is there a reference or reference link you can share. i would love to do that. that is workable for me. Probably a continues looped stdin and stdout – Gary Apr 22 '23 at 13:52
  • 1
    Maybe start here https://stackoverflow.com/a/49715256/2308683 – OneCricketeer Apr 22 '23 at 13:56
  • 1
    You don't have to marshal the input back and forth. You just have to include `os.Stdin` when redirecting the input and output to python. – erik258 Apr 22 '23 at 16:43
  • @erik258 thank you. i tried that and it failed with just a single stdin like this `cmd := exec.Command("python3"); cmd.Stdin = os.Stdin`. Maybe there was some issue since i am quite new to golang from python – Gary Apr 23 '23 at 02:53
  • @OneCricketeer can you put yours as the answer? I wish to mark it right. bufio worked for me. let me have a look at the api if i need to drill down. `scanner := bufio.NewScanner(os.Stdin); for{fmt.Print("Enter Text: ");scanner.Scan();text := scanner.Text();if len(text) != 0 {` – Gary Apr 23 '23 at 02:58
  • "i tried that and it failed" there's a complete working example in my answer. If you tried it and it didn't work for you, you made a mistake. Or maybe it works different in windows where everything is a little wacky? – erik258 Apr 23 '23 at 12:54
  • @erik258 the demo worked. but not for looped `stdin` and `stdout`. i am on windows and am expecting this to work with all linux, mac, and windows. – Gary Apr 23 '23 at 15:14

1 Answers1

2

If your go program's stdin and stdout is a terminal, and you set your exec.Command's stdout and stdin to the go program's stdout and stdin, you can indeed expect python (in this case) to interact with the terminal just like it was executed directly.

This code:

package main
import(
    "os"
    "os/exec"
)

func main() {
    cmd := exec.Command("python3")
    cmd.Stdin = os.Stdin
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    if err := cmd.Run(); err != nil {
        panic(err)
    }
}

Has this behavior:

% go run t.go                                                                                                                                                                                       
Python 3.9.6 (default, Aug  5 2022, 15:21:02)
[Clang 14.0.0 (clang-1400.0.29.102)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print("hello world")
hello world
>>> exit
Use exit() or Ctrl-D (i.e. EOF) to exit
>>> ^D
[2023/04/22 11:31:20 CDT ] ~

Your code was missing cmd.Stdin = os.Stdin.

erik258
  • 14,701
  • 2
  • 25
  • 31