i'm developing a Go application, which should be able to run python scripts. the scripts are located inside scripts/python
folder, and i include them in the go binary using //go:embed
annotation, and then run them using exec.Command
, the following way:
package main
import (
"embed"
_ "embed"
"fmt"
"os"
"os/exec"
"strings"
)
//go:embed scripts/python/argsTest.py
var argsTestScript string
func main() {
args:= []string{}
runCommand(args, argsTestScript)
}
func runCommand(args []string, scriptFile string) {
c := exec.Command("python", args...)
c.Stdin = strings.NewReader(scriptFile)
output, err := c.Output()
if err != nil {
fmt.Println("error = ", err)
return
}
fmt.Println("output = ", string(output))
}
when argTest.py
simply prints the arguments -
import sys
print('Number of arguments:', len(sys.argv), 'arguments.')
print('Argument List:', str(sys.argv))
if i don't send any arguments it works fine, however when i do send any argument i get exit status 2
, and inside stderr
i get python: can't open file 'x': [Errno 2] No such file or directory
(if i send a single argument x
). i understand that this happens because when there are arguments, the exec.Command
behaves as if the first one is the python script that should be executed.
one way of overcoming this should be extracting the script file's path (and not its content, which is what argsTestScript
var holds). i tried doing so by setting this var to be of type embed.FS
instead of string, but i could only find a way to extract the file name, not its full path.
is there any way to achieve this? either trick the exec.Command
to receive the arguments after the script file, or extract the script file path? or any other option?
cheers, eRez
CodePudding user response:
as @JimB mentioned above - when using stdin and sending arguments to the python method - the first argument should simply be -
args:= []string{"-", "x", "y", "z"}
however make sure your python method ignores this hyphen, as the output of my go script will be -
output = Number of arguments: 4 arguments.
Argument List: ['-', 'x', 'y', 'z']