go-python

视觉智慧实践课上需要写深度学习-图像检索的大作业。Python是机器/深度学习御用开发语言,Golang是新时代后端开发语言。Python很适合算法写模型,而Golang很适合提供API服务,两位同志都红的发紫。(抄袭)

所以算法方面用python写的sift,qt不想写(不喜欢),最近又在学go,所以准备用gin搭建web端,不过go和python之间好像有什么联系,没错,就是go-python,所以开始吧。

go-python

1
go get -u github.com/DataDog/go-python3

我的mac是python3.9版本的,所以在go build的时候报错:

1
2
## github.com/DataDog/go-python3
../../go/pkg/mod/github.com/!data!dog/go-python3@v0.0.0-20211102160307-40adc605f1fe/dict.go:141:13: could not determine kind of name for C.PyDict_ClearFreeList

意思就是python3.9的这个函数PyDict_ClearFreeList被删除了,找不到

通过查看这个issue可以发现:

  • python的版本需要用3.7,所以需要配置python3.7虚拟环境
  • 下好之后,需要用到pkg-config

解决方案:

下载python3.7,然后用anaconda或者venv创建虚拟环境。

我通过brew install pkg-config,然后export $PKG_CONFIG_PATH=/usr/local/bin/pkg-config,还是不太行。 原来需要用到python3.7里的pkg-config。

直接执行下面:

1
2
3
sudo vim ~/.bash_profile
export $PKG_CONFIG_PATH=/Library/Frameworks/Python.framework/Versions/3.7/lib/pkgconfig
source ~/.bash_profile

最后go build可以顺利完成。

go调用python的过程

  1. 初始化python环境
  2. 引入模块py对象
  3. 使用该模块的变量与函数
  4. 解析结果
  5. 销毁python3运行环境

调用中必用到到几个函数

init func()

1
2
3
4
5
6
7
func init() {
python3.Py_Initialize()
if !python3.Py_IsInitialized() {
fmt.Printf("Error initializing the python interpreter")
os.Exit(1)
}
}

ImportModule func(dir, name strng) *python3.PyObject

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ImportModule
// @Description: 导入一个包
// @param dir
// @param name
// @return *python3.PyObject
func ImportModule(dir, name string) *python3.PyObject {
sysModule := python3.PyImport_ImportModule("sys")
path := sysModule.GetAttrString("path")
pathStr, _ := pythonRepr(path)
log.Println("before add path is " + pathStr)
python3.PyList_Insert(path, 0, python3.PyUnicode_FromString(""))
python3.PyList_Insert(path, 0, python3.PyUnicode_FromString(dir))
pathStr, _ = pythonRepr(path)
log.Println("after add path is " + pathStr)
return python3.PyImport_ImportModule(name)
}

pythonRepr func(o *python3.PyObject) (string, error)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// pythonRepr
// @Description: PyObject转换为string
// @param o
// @return string
// @return error
func pythonRepr(o *python3.PyObject) (string, error) {
if o == nil {
return "", fmt.Errorf("object is nil")
}
s := o.Repr()
if s == nil {
python3.PyErr_Clear()
return "", fmt.Errorf("failed to call Repr object method")
}
defer s.DecRef()

return python3.PyUnicode_AsUTF8(s), nil
}

本文作者:jujimeizuo
本文地址https://blog.jujimeizuo.cn/2022/05/17/go-python/
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0 协议。转载请注明出处!