在Golang代码中使用Python的方法

在Golang代码中使用Python的方法 我需要在我的Go代码中使用Python代码。 我写了以下示例,但无法运行它:

package main

// #cgo pkg-config: python3
// #include "/usr/include/python3.11/Python.h"
import "C"
import "fmt"

func main() {
	C.Py_Initialize()
	fmt.Println(C.GoString(C.Py_GetVersion()))
	C.Py_Finalize()
}
链接器错误
# command-line-arguments
/usr/local/go/pkg/tool/linux_amd64/link: running gcc failed: exit status 1
/usr/bin/ld: /tmp/go-link-3756148642/000001.o: in function `_cgo_d10853a22200_Cfunc_Py_GetVersion':
/tmp/go-build/cgo-gcc-prolog:63: undefined reference to `Py_GetVersion'
/usr/bin/ld: /tmp/go-link-3756148642/000001.o: in function `_cgo_d10853a22200_Cfunc_Py_Finalize':
/tmp/go-build/cgo-gcc-prolog:49: undefined reference to `Py_Finalize'
/usr/bin/ld: /tmp/go-link-3756148642/000001.o: in function `_cgo_d10853a22200_Cfunc_Py_Initialize':
/tmp/go-build/cgo-gcc-prolog:78: undefined reference to `Py_Initialize'
collect2: error: ld returned 1 exit status

操作系统:Fedora release 37 (Thirty Seven) Go版本:go version go1.19.5 linux/amd64 Python版本:Python 3.11.1 gcc版本:gcc (GCC) 12.2.1 20221121 (Red Hat 12.2.1-4)


更多关于在Golang代码中使用Python的方法的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

我猜Go找不到libpython3。你的python3.pc文件内容是什么?

更多关于在Golang代码中使用Python的方法的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


遗憾的是,它仍然无法工作。

我从未这样做过,但我想 Libs 或 Libs.private 中应该包含 -lpython3

哦,明白了!

python3-embed                  Python - 将Python嵌入到应用程序中
python3                        Python - 为Python构建C扩展

我需要的是 python3-embed,而不是 python3

以下是 /usr/lib64/pkgconfig/python3.pc 文件的内容:

# See: man pkg-config
prefix=/usr
exec_prefix=/usr
libdir=/usr/lib64
includedir=/usr/include

Name: Python
Description: Build a C extension for Python
Requires:
Version: 3.11
Libs.private: -ldl 
Libs:
Cflags: -I${includedir}/python3.11

在Go中嵌入Python需要正确配置CGO的编译和链接参数。你的代码缺少链接Python库的指令。以下是修正后的示例:

package main

// #cgo pkg-config: python3-embed
// #include <Python.h>
import "C"
import (
    "fmt"
    "unsafe"
)

func main() {
    C.Py_Initialize()
    
    // 获取Python版本
    version := C.Py_GetVersion()
    fmt.Println(C.GoString(version))
    
    // 执行Python代码示例
    code := C.CString("print('Hello from Python!')")
    defer C.free(unsafe.Pointer(code))
    
    C.PyRun_SimpleString(code)
    
    C.Py_Finalize()
}

编译时需要确保pkg-config能找到正确的Python配置:

# 安装Python开发包(Fedora)
sudo dnf install python3-devel

# 设置CGO环境变量并编译
export CGO_CFLAGS=$(pkg-config --cflags python3-embed)
export CGO_LDFLAGS=$(pkg-config --libs python3-embed)
go build -o main main.go

如果需要更复杂的交互,可以使用以下扩展示例:

package main

// #cgo pkg-config: python3-embed
// #include <Python.h>
import "C"
import (
    "fmt"
    "unsafe"
)

func main() {
    C.Py_Initialize()
    
    // 导入模块并调用函数
    moduleName := C.CString("math")
    defer C.free(unsafe.Pointer(moduleName))
    
    mathModule := C.PyImport_ImportModule(moduleName)
    if mathModule == nil {
        panic("Failed to import math module")
    }
    defer C.Py_DecRef(mathModule)
    
    // 调用math.sqrt(16)
    funcName := C.CString("sqrt")
    defer C.free(unsafe.Pointer(funcName))
    
    sqrtFunc := C.PyObject_GetAttrString(mathModule, funcName)
    if sqrtFunc == nil {
        panic("Failed to get sqrt function")
    }
    defer C.Py_DecRef(sqrtFunc)
    
    arg := C.PyFloat_FromDouble(16.0)
    defer C.Py_DecRef(arg)
    
    args := C.PyTuple_New(1)
    C.PyTuple_SetItem(args, 0, arg)
    
    result := C.PyObject_CallObject(sqrtFunc, args)
    if result != nil {
        defer C.Py_DecRef(result)
        value := C.PyFloat_AsDouble(result)
        fmt.Printf("math.sqrt(16) = %f\n", value)
    }
    
    C.Py_Finalize()
}

注意:Fedora 37中Python 3.11的pkg-config名称可能是python3.11而不是python3-embed。如果遇到问题,可以尝试:

// 替代方案:直接指定库路径
// #cgo LDFLAGS: -lpython3.11
// #include <Python.h>

或者检查可用的pkg-config名称:

pkg-config --list-all | grep python
回到顶部