运行带参数的嵌入式脚本的Go代码。

huangapple go评论89阅读模式
英文:

Go - run embed script with arguments

问题

我正在开发一个Go应用程序,它应该能够运行Python脚本。这些脚本位于scripts/python文件夹中,并且我使用//go:embed注释将它们包含在Go二进制文件中,然后使用exec.Command来运行它们,代码如下:

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

argTest.py简单地打印参数时:

import sys

print('Number of arguments:', len(sys.argv), 'arguments.')
print('Argument List:', str(sys.argv))

如果我不发送任何参数,它可以正常工作,但是当我发送任何参数时,我会得到exit status 2,并且在stderr中我会得到python: can't open file 'x': [Errno 2] No such file or directory(如果我发送一个单独的参数x)。我理解这是因为当有参数时,exec.Command的行为就好像第一个参数是应该执行的Python脚本。

一种解决方法是提取脚本文件的路径(而不是其内容,这是argsTestScript变量所保存的内容)。我尝试通过将该变量设置为embed.FS类型而不是字符串来实现这一点,但我只找到了提取文件名而不是完整路径的方法。

有没有办法实现这一点?要么欺骗exec.Command在脚本文件之后接收参数,要么提取脚本文件的路径?或者还有其他选项吗?

谢谢,
eRez

英文:

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

答案1

得分: 1

如@JimB在上面提到的-当使用stdin并向Python方法发送参数时-第一个参数应该简单地是-

args:= []string{"-", "x", "y", "z"}

但是请确保你的Python方法忽略这个连字符,因为我的Go脚本的输出将是-

output = 参数数量:4个参数。
参数列表:['-', 'x', 'y', 'z']
英文:

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

huangapple
  • 本文由 发表于 2022年4月13日 22:01:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/71858823.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定