Go – run embed script with arguments

Issue

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

Solution

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']

Answered By – eRez

Answer Checked By – Senaida (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.