在项目文件夹中运行Python脚本的Golang实现方法

在项目文件夹中运行Python脚本的Golang实现方法 我正在尝试在我的Go项目文件夹中运行一个Python脚本,但不知道该如何运行它。

目前已有的代码:

func runProgram(target string) {
	output, err := exec.Command(target).Output()
	if err != nil {
		panic(err.Error())
	}
	fmt.Println(string(output))
}

我执行该函数的方式:

func auditTask() {
	runProgram("linuxScanner")
}

我一直收到以下错误:

panic: exec: “linuxScanner”: executable file not found in $PATH

我还需要能够将Python脚本与Go代码打包在同一个可执行文件中


更多关于在项目文件夹中运行Python脚本的Golang实现方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

15 回复

你可以在这里放置任何你喜欢的字符串。

更多关于在项目文件夹中运行Python脚本的Golang实现方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


非常感谢!

还有一个问题,我该如何运行整个Python脚本,而不是仅仅执行 print("hello")

抱歉,这可能听起来像个新手问题,但我该如何处理一个大约有100行长的字符串呢?

谢谢!但不幸的是,我遇到了这个错误:

fork/exec python: no such file or directory

NobbZ:

将内容写入 Python 的标准输入来运行它

我该如何实现这个操作?

他甚至应该能够将其写入 Python 的标准输入来运行。这样就不需要创建可能涉及权限问题的临时文件(虽然通常不会出现这种情况)。

NobbZ:

出于某些原因,go 有时会打印这些信息。

当你使用 go run 命令时就会出现这种情况。

如果可执行文件不在 PATH 环境变量中,你需要指定可执行文件的路径,可以是绝对路径或相对路径(当前工作目录使用前导 ./)。

如下所示:

const longString = `#!/usr/bin/env python

lorem
ipsum
dolor
est
imet
and
many
more
lines
with
actual
code
`

首先,感谢您的帮助!

我还有另一个问题(希望是最后一个)。我一直收到这个错误:

panic: exit status 1

然后在堆栈跟踪之后,我还看到:

exit status 2

正如Norbert所说,您必须将linuxScanner放在$PATH变量指定的目录中,或者使用相对路径./linuxScanner(点号表示当前目录),或者使用绝对路径如/home/xxx/my-folder/another-folder/linuxScanner。

如果您想将脚本嵌入到Go程序中,可以按照以下方式实现:

package main

# 反引号用于多行原始字符串
var pythonProgram = `
#!/usr/bin/python

a = "World"
print "Hello " + a
`

然后使用https://golang.org/pkg/io/ioutil/#TempFile将程序写入临时文件,再执行该文件。

这是凭记忆写的,而且我不确定需要如何调用 python 才能从标准输入获取内容,因此您可能需要稍作调整:

package main

import (
	"bytes"
	"fmt"
	"os/exec"
	"strings"
)

func main() {
	cmd := new(exec.Cmd)
	r := strings.NewReader(`print("hello")`)
	var o bytes.Buffer

	cmd.Path = "python"
	cmd.Stdin = r
	cmd.Stdout = &o

	if err := cmd.Run(); err != nil {
		panic(err)
	}

	fmt.Println("%v", o.String())
}

我猜你是直接从我的示例中复制了 if err := cmd.Run(); err != nil { panic(err) } 这段代码?

所以你的 Python 脚本执行了类似 exit(1) 的操作,这会被理解为执行错误(任何非 0 的返回值都被视为错误),因此会给你一个无用的错误信息,提示执行因 exit status x 而失败。解析这条信息是可靠获取退出代码的唯一方法。

第二个 exit status 2 是你的 Go 程序的退出状态。出于某些原因,Go 有时会打印这个信息。

if err := cmd.Run(); err != nil { panic(err) }

抱歉……我查看了我之前做过类似功能的旧项目,发现我记错了如何创建 exec.Cmd 结构体。

这里有一个修复初始化问题的小补丁,同时也修正了 fmt.Println 的调用 😉

--- x   2018-10-06 08:28:45.734796606 +0200
+++ main.go     2018-10-06 08:27:34.618183208 +0200
@@ -10,3 +10,3 @@
 func main() {
-       cmd := new(exec.Cmd)
+       cmd := exec.Command("python")
        r := strings.NewReader(`print("hello")`)
@@ -14,3 +14,2 @@

-       cmd.Path = "python"
        cmd.Stdin = r
@@ -22,3 +21,3 @@

-       fmt.Println("%v", o.String())
+       fmt.Println(o.String())
 }

要解决在Go项目中运行Python脚本的问题,需要明确几个关键点:Python脚本不是可执行二进制文件,必须通过Python解释器运行;同时需要处理脚本路径和打包问题。以下是完整的解决方案:

首先修改runProgram函数,明确指定使用Python解释器并传递脚本路径:

func runPythonScript(scriptPath string) {
    // 使用python3执行指定路径的脚本
    cmd := exec.Command("python3", scriptPath)
    output, err := cmd.Output()
    if err != nil {
        panic(fmt.Sprintf("执行Python脚本失败: %v", err))
    }
    fmt.Println(string(output))
}

然后在项目中调用:

func auditTask() {
    // 假设Python脚本位于项目根目录,名为linuxScanner.py
    runPythonScript("./linuxScanner.py")
}

对于打包到单个可执行文件的需求,需要使用Go的embed功能。首先创建嵌入Python脚本的代码:

import (
    _ "embed"
    "os"
    "os/exec"
    "path/filepath"
)

//go:embed linuxScanner.py
var pythonScriptContent string

func runEmbeddedPythonScript() {
    // 创建临时文件
    tmpfile, err := os.CreateTemp("", "script-*.py")
    if err != nil {
        panic(fmt.Sprintf("创建临时文件失败: %v", err))
    }
    defer os.Remove(tmpfile.Name()) // 清理临时文件

    // 写入嵌入的Python脚本内容
    if _, err := tmpfile.WriteString(pythonScriptContent); err != nil {
        panic(fmt.Sprintf("写入临时文件失败: %v", err))
    }
    if err := tmpfile.Close(); err != nil {
        panic(fmt.Sprintf("关闭临时文件失败: %v", err))
    }

    // 执行Python脚本
    cmd := exec.Command("python3", tmpfile.Name())
    output, err := cmd.Output()
    if err != nil {
        panic(fmt.Sprintf("执行Python脚本失败: %v", err))
    }
    fmt.Println(string(output))
}

使用嵌入版本:

func auditTask() {
    runEmbeddedPythonScript()
}

项目结构示例:

project/
├── main.go
├── linuxScanner.py (将被嵌入)
└── go.mod

main.go同目录下创建linuxScanner.py文件,内容示例:

#!/usr/bin/env python3
print("Python脚本执行成功!")

确保系统已安装Python3,编译Go程序时会自动将Python脚本嵌入到可执行文件中。这种方法既解决了路径问题,也实现了单文件分发的需求。

回到顶部