咨询热线:13634735304 联系人:王裕凯 地址:广西自治省柳州市鱼峰区阳和科技创新园3号厂房
Golang 调用 Python 代码
来源:yabo客户端 发布时间:2019-06-26 点击量:15
go 中的 cgo 模块可以让 go 无缝调用 c 或者 c++ 的代码,而 python 本身就是个 c 库,自然也可以由 cgo 直接调用,前提是指定正确的编译条件,如 Python.h 头文件(),以及要链接的库文件。本文以 Ubuntu 18.04 作为开发和运行平台进行演示。
其实在使用 cgo 之前,笔者也考虑过使用 grpc 的方式。比如可以将需要调用的 python 代码包装成一个 grpc server 端,然后再使用 go 编写对应的 client 端,这样考虑的前提是,go 调用 python 代码本来就是解一时之困,而且引入语言互操作后,对于项目维护和开发成本控制都有不小的影响,如果直接使用 grpc 生成编程语言无感知的协议文件,将来无论是重构或使用其他语言替换 python 代码,都是更加方便,也是更加解耦的。所以 grpc 也是一种比较好的选择。至于通信延迟,老实说既然已经设计语言互操作,本机中不到毫秒级的损失其实也是可以接受的。
接下来进入正题。
1. 针对 python 版本安装 python-dev
sudo apt install python3.6-dev
系统未默认安装 python3.x 的开发环境,所以假如要通过 cgo 调用 python,需要安装对应版本的开发包。
2. 指定对应的cgo CFLAGS 和 LDFLAGS 选项
对于未由 c 包装的 python 代码,python-dev 包中内置了 python-config 工具用于查看编译选项。
python3.6-config --cflagspython3.6-config --ldflags
以下是对应的输出
-I/usr/include/python3.6m -I/usr/include/python3.6m -Wno-unused-result -Wsign-compare -g -fdebug-prefix-map=/build/python3.6-MtRqCA/python3.6-3.6.6=. -specs=/usr/share/dpkg/no-pie-compile.specs -fstack-protector -Wformat -Werror=format-security -DNDEBUG -g -fwrapv -O3 -Wall-L/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/usr/lib -lpython3.6m -lpthread -ldl -lutil -lm -xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions
低版本的 python 也可以在安装开发包后,使用对应的 python-config 命令打印依赖配置。由于 cgo 默认使用的编译器不是 gcc ,所以输出中的部分选项并不受支持,所以最后 cgo 代码的配置为
//#cgo CFLAGS : -I./ -I/usr/include/python3.6m//#cgo LDFLAGS: -L/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/usr/lib -lpython3.6m -lpthread -ldl -lutil -lm//#include "Python.h"import "C"
3. 部分示例代码
3.0 映射 PyObject
type PyObject struct { ptr *C.PyObject}func togo(obj *C.PyObject) *PyObject { if obj == nil { return nil } return &PyObject{ptr: obj}}func topy(self *PyObject) *C.PyObject { if self == nil { return nil } return self.ptr}
3.1 python 环境的启动与终结
func Initialize() error { if C.Py_IsInitialized() == 0 { C.Py_Initialize() } if C.Py_IsInitialized() == 0 { return fmt.Errorf("python: could not initialize the python interpreter") } if C.PyEval_ThreadsInitialized() == 0 { C.PyEval_InitThreads() } if C.PyEval_ThreadsInitialized() == 0 { return fmt.Errorf("python: could not initialize the GIL") } return nil}func Finalize() error { C.Py_Finalize() return nil}
3.2 包路径与模块导入
func InsertExtraPackageModule(dir string) *PyObject { sysModule := ImportModule("sys") path := sysModule.GetAttrString("path") cstr := C.CString(dir) defer C.free(unsafe.Pointer(cstr)) C.PyList_Insert(topy(path), C.Py_ssize_t(0), topy(togo(C.PyBytes_FromString(cstr)))) return ImportModule(dir)}func ImportModule(name string) *PyObject { c_name := C.CString(name) defer C.free(unsafe.Pointer(c_name)) return togo(C.PyImport_ImportModule(c_name))}func (self *PyObject) GetAttrString(attr_name string) *PyObject { c_attr_name := C.CString(attr_name) defer C.free(unsafe.Pointer(c_attr_name)) return togo(C.PyObject_GetAttrString(self.ptr, c_attr_name))}
3.3 数据类型转换
func PyStringFromGoString(v string) *PyObject { cstr := C.CString(v) defer C.free(unsafe.Pointer(cstr)) return togo(C.PyBytes_FromString(cstr))}func PyStringAsGoString(self *PyObject) string { c_str := C.PyBytes_AsString(self.ptr) return C.GoString(c_str)}...
可以看到形似 C.Py*
的方法都是由 cgo 模块编译调用的,这些方法也是 python 暴露的 C-API,而这里的示例就到此为止,其他诸如调用 python 模块方法的功能文档里也描述得十分详细,尽管实施起来仍然有些麻烦。
但是请注意 C-API 的 2.x 与 3.x 版本仍有不同,比如 2.x 版本中的字符串操作类型 PyString_*
在 3.x 中便被重命名为 PyBytes_*
。
关注过 go 与 python 互操作功能的同学应该注意到上述的示例代码部分来自 go-python 这个开源项目,有兴趣的同学也可以关注一下。 这个项目基于 python2.7 ,其中暴露的 api 诸如字符串转换也是基于 python2.x 版本,所以针对于更流行的 python3.x 项目,大家就需要自己按照上文方法做一些修改了。
实际工作中,语言的互操作场景确实很让人感觉头疼,而 cgo 的文档资料其实并不多,所以希望本文能给大家带来一些帮助。
相关产品
-
蚌埠市固镇县92岁老人王挺珍求助媒体,欲寻找失散54年的女儿“小凤”,希望有生之年能再看一眼日夜思念的女儿。看似渺茫的寻亲之路迎来转折:怀远的王先生看到本报的相关报道后,致电晨刊热线,称其姐姐何永云,可能就是“小凤”。怀着惊喜、期待与不安,王挺珍的小儿子胡先生,驱车来到怀远,与何永云相见时,有见到家人的感觉,分外开心。然而,1月3日,亲子鉴定机构给出了这样的答复:何永云并不是王挺珍的亲生女儿。
-
刺青师丁世裕说,一般客人提供刺青的照片都是容光焕发画面,这是第一次客人拿来的照片每张都插着呼吸管,他花了一礼拜完成修图,让照片中的男婴面色圆润,眼睛有神。
-
在盛典上,腾讯汽车总监王秋凤首次发布了《腾讯自主品牌汽车用户白皮书》。该白皮书是通过对腾讯汽车50万自主品牌潜在客户的购车意向数据、腾讯各平台上上亿份的用户行为数据以及1万份有针对性性的在线调查问卷数据进行深入分析,由此得出的一份关于自主品牌汽车用户购车偏好、用户画像、兴趣爱好、生活轨迹、消费习惯等特征的报告。
-
出差回来第二天,任斌夹着李毅送的包上班。同事老吴见了打趣道:“呦呵,换包了,是从省城地摊上淘的吧?”任斌说了大款发小送包的事,老吴上前细看,好一会儿才道:“的确是上等品质,只是样式不适合你,别的我就不多说了,呵呵。”
-
“抓获了这样的划车者,不能罚款了事,而是应从根本上解决他的心理问题。”邱驷认为,长期的划车成瘾是一种扭曲的心理减压,对这些人来说,并不是单纯地批评教育就能改变其已经成为习惯的做法。重庆晨报记者 景然 报道
-
对于美国因素将产生什么影响,朱卫东认为,经过一段磨合期后,美国新政府会逐步认清一中原则,回到原来正确的轨道上。
-
在上车前要绕车一周,除检查车况外,就是看看周围有无障碍物躲在盲区里。倒车时最好将车窗打开,关闭电台,以便出现异常能够听到。
-
摩根士丹利中国首席经济学家邢自强(Robin Xing)认为,中国像盐城这样的小城市,它们消费支出的增速将继续超过大城市。因此,到2030年,中国私人消费增长的三分之二将来自这些地区。
热点资讯
- “法式生活艺术巡展”成功举办,聚焦家居领域的传统与创新10月24日-26日,35个法国顶级家居品牌齐聚北京2019-06-26
- 荷兰电池厂商与中国合作伙伴在华建厂投资近19亿美元2019-06-26
- 《爱情公寓》电影版首曝预告:曾小贤、胡一菲等集体变装2019-06-26
- 3827元起,微软认证翻新SurfacePro5/Laptop上架官方商城2019-06-26
- 韩媒专访RNG主教练Heart:Uzi操作非人类队员坦言从未如此努力过2019-06-26
- 腾讯团队发现了SQLite的漏洞:或者影响成千上万的应用程序,比如Chrome|Chrome|Ten.|SQLite_SinaTechnologies。2019-06-26
- 土耳其警方拘捕两名美使馆枪击案嫌疑人:均为土耳其公民2019-06-26
- ofo小黄车与蚂蚁森林合作到期:骑行不再获取能量2019-06-26