在go中使用C API调用CPython库,从而可以进行Python语法调用。可用pip安装库,然后go语言可直接访问python方法。
项目路径本文使用python3 版本
github.com/go-python/cpy3
附: python2版本
github.com/go-python/cpy2
下载python3.7.9
选择自定义安装,安装所有组件
安装路径设置为C:/Python37
喜欢用便携版的可以参照这里安装便携版
然后从安装版中拷贝include到便携版目录中即可.
include目录是pkg-config的前置条件.
先安装choco
使用命令安装pkg-config
choco install pkgconfiglite
新增PC文件
如下路径新增文件
%USERPROFILE%\.pkgconfig\python3.pc
PYTHTON_HOME=C:/Python37
lib=${PYTHTON_HOME}
include=${PYTHTON_HOME}/include
Name: Python
Description: Python library
Requires:
Version: 3.7
Libs: -L${lib} -lpython37 -lpthread -lm
Cflags: -I${include} -DMS_WIN64
安装TMD-GCC
下载TMD-GCC并安装
官网地址
设置pkg_config环境变量
setx PKG_CONFIG_LIBDIR %USERPROFILE%\.pkg-config
或者
setx PKG_CONFIG_PATH %USERPROFILE%\.pkg-config
设置Go环境变量
setx GOOS windows
setx GOARCH amd64
setx CGO_ENABLED 1
setx GO111MODULE auto
如果是vscode,在setting.json中添加,否则语法提示无法正常工作
{
"go.toolsEnvVars": {
"GOOS": "windows",
"GOARCH": "amd64",
"CGO_ENABLED": "1",
"GO111MODULE": "auto",
}
}
安装go-python
go get -v github.com/go-python/cpy3
测试
python3版本的API和python2版本的API略有区别。修正后的测试程序
package main
import (
"fmt"
python3 "github.com/go-python/cpy3"
)
func main() {
python3.Py_Initialize()
gostr := "foo"
bytes := python3.PyBytes_FromString(gostr)
str := python3.PyBytes_AsString(bytes)
fmt.Println("hello [", str, "]")
}
显示
hello [ foo ]
不兼容接口
官网文档指明:Windows下File的结构可能因为链接库的不同而不同。
由于Python3在windows上是MSVC的,而golang并不支持MSVC,从而使用了TMD-GCC来兼容。这样File肯定不一样。则PyRun_AnyFile 不可使用。
Py_Main() 则需要额外多传递一个参数。这个非File*指针所致, *** 作系统区别而已。
使用示例
package main
import (
"fmt"
"log"
"os"
python3 "github.com/go-python/cpy3"
)
func main() {
defer python3.Py_Finalize()
python3.Py_Initialize()
cwd, err := os.Getwd()
if err != nil {
log.Panic(err)
}
code := python3.PyRun_SimpleString(fmt.Sprintf(`
import sys
sys.path.append(r"%s")
`, cwd))
if code != 0 {
log.Panic(fmt.Errorf("call `PyRun_SimpleString` error"))
}
f, err := os.Create("test.py")
if err != nil {
panic(err)
}
defer func() {
if err := f.Close(); err != nil {
panic(err)
}
}()
if _, err := f.WriteString(`
print("test")
`); err != nil {
panic(err)
}
code, err = python3.Py_Main([]string{"python", "test.py"})
if err != nil {
panic(err)
}
if code != 0 {
log.Panic(fmt.Errorf("call `Py_Main` error"))
}
}
由于CPython API的原因没有AP可以对sys.path进行直接的 *** 作,只能通过执行String的模式来更改
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)