共计 3295 个字符,预计需要花费 9 分钟才能阅读完成。
简介: # 简介 ## go-python Python 提供了丰盛的[C-API](https://docs.python.org/2/c-a…。而 C 和 Go 又能够通过 cgo 无缝集成。所以,间接通过 Golang 调用 libpython,就能够实现 Go 调 Python 的性能了。然而过程比较复杂,而[go-python](https://github.com/sbinet/go-…
简介
go-python
Python 提供了丰盛的 C -API。而 C 和 Go 又能够通过 cgo 无缝集成。所以,间接通过 Golang 调用 libpython,就能够实现 Go 调 Python 的性能了。然而过程比较复杂,而 go-python 提供了针对 CPython- 2 的 C -API 提供了 native-binding 能力,不便实现了 Go 到 Python 的调用。
然而目前,go-python 只反对 python2.7。
pkg-config
go-python
应用 pkg-config
来获取 python 的头文件及库信息。
一般来说,如果库的头文件不在 /usr/include 目录中,那么在编译的时候须要用 - I 参数指定其门路。因为同一个库在不同零碎上可能位于不同的目录下,用户装置库的时候也能够将库装置在不同的目录下,所以即便应用同一个库,因为库的门路的不同,造成了用 - I 参数指定的头文件的门路和在连贯时应用 - L 参数指定 lib 库的门路都可能不同,其后果就是造成了编译命令界面的不对立。pkg-config
就是用来解决编译连贯界面不对立问题的一个工具。
pkg-config
的根本思维是通过库提供的一个.pc 文件取得库的各种必要信息的,包含版本信息、编译和连贯须要的参数等。这样,不论库文件装置在哪,通过库对应的.pc 文件就能够精确定位,能够应用雷同的编译和连贯命令,使得编译和连贯界面对立。
环境配置(MAC 为例)
1、本地找到 python-2.7.pc 文件。如果没有则创立一个。特地留神,prefix 要指定为 python2.7 的 library 门路。
# See: man pkg-config
prefix=/System/Library/Frameworks/Python.framework/Versions/2.7
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: Python
Description: Python library
Requires:
Version: 2.7
Libs.private: -ldl -framework CoreFoundation
Libs: -L${libdir} -lpython2.7
Cflags: -I${includedir}/python2.7
2、将 python-2.7.pc 门路增加到环境变量 $PKG_CONFIG_PATH 中
3、验证后果:pkg-config –cflags — python-2.7
-I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7
4、执行 make VERBOSE=1,第一次执行可能会提醒 go-python 命令找不到。将 gopath 的 bin 门路增加到环境变量 $PATH 即可。如下图 ut 通过,阐明配置胜利了。
5、独自执行 test。须要增加下 PYTHONPATH 环境变量,否则将导入不了 python 包。
export PYTHONPATH=.:$PYTHONPATH
cd go-python/tests/kw-args
go run main.go
importing kwargs...
args=() kwds={}
args=() kwds={'a': 3}
样例
应用 python 的 cPickle 模块,通过 dumps 将 python 对象序列化保留到一个字符串变量中,通过 loads 从字符串变量中载入 python 对象。
package main
import (
"fmt"
"github.com/sbinet/go-python"
)
// 初始化 go-python
func init() {err := python.Initialize()
if err != nil {panic(err.Error())
}
}
func main() {
gostr := "foo" // 定义 goloang 字符串
pystr := python.PyString_FromString(gostr) // 将 golang 字符串专程 python 字符串
str := python.PyString_AsString(pystr) // 将 python 字符串,再转为 golang 字符串。fmt.Println("hello [", str, "]")
pickle := python.PyImport_ImportModule("cPickle") // 导入 cPickle 模块
if pickle == nil {panic("could not import'cPickle'")
}
dumps := pickle.GetAttrString("dumps") // 获取 dumps 函数
if dumps == nil {panic("could not retrieve'cPickle.dumps'")
}
defer dumps.DecRef() // 缩小援用计数,开释资源。out := dumps.CallFunctionObjArgs("O", pystr) // 针对 python 字符串进行 dumps 操作。if out == nil {panic("could not dump pystr")
}
defer out.DecRef()
fmt.Printf("cPickle.dumps(%s) = %q\n", gostr,
python.PyString_AsString(out),
)
loads := pickle.GetAttrString("loads") // 获取 loads 函数
if loads == nil {panic("could not retrieve'cPickle.loads'")
}
defer loads.DecRef()
out2 := loads.CallFunctionObjArgs("O", out) // 将 dumps 后果从新 loads
if out2 == nil {panic("could not load back out")
}
defer out2.DecRef()
fmt.Printf("cPickle.loads(%q) = %q\n",
python.PyString_AsString(out),
python.PyString_AsString(out2),
)
}
机制简介
整个 go-python 的外围在于解决 PyObject
跟 golang 类型的关系。在 Python 外部,PyObject
构造体用来保留全副对象独特的数据成员,以及实现 GC 机制所须要的一些辅助字段等,所以说PyObject
Python 对象机制的根底。
- sequence.go:解决了
PyObject
跟 golang 内置类型的转换。典型的例如:PyString_FromString 是将 golang string 转换为 python string,即 PyObject;PyString_AsString 是将 PyObject 转换为 golang string。 -
object.go:对于 PyObject 的一些外围操作。例如:获取函数对象 GetAttr,及响应函数对象的调用 CallFunctionObjArgs 等。
- 其本质是对 python C 扩大的封装。如下所示:
func (self *PyObject) GetAttr(attr_name *PyObject) *PyObject {return togo(C.PyObject_GetAttr(self.ptr, attr_name.ptr))
}
注意事项:
所有的 PyObject 对象应用完结,须要被动调用 DecRef,通过缩小援用计数的形式开释对象,否则会产生内存透露。
原文链接
本文为阿里云原创内容,未经容许不得转载。