golang调用python实战
简介
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机制所须要的一些辅助字段等,所以说PyObjectPython对象机制的基础。
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,通过减少引用计数的方式释放对象,否则会产生内存泄漏。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Apache DolphinScheduler 1.3.2 发布,性能提升 2~3 倍
引言 大数据任务调度作为大数据建设中的核心基础设施,在经过社区用户们长期的使用中,不少用户对调度也提出了很多新的要求,为此,Apache DolphinScheduler(Incubating)经过长达 5 个多月的辛苦努力, 终于发布了 1.3.2 正式版本。DolphinScheduler-1.3.2 有超过 30 名贡献者参与开发,性能较 1.2 版本有 2 ~ 3 倍的提升,相对 1.2 版本,1.3.x 增加了诸如 K8s支持、多目录管理等重要的新特性和新的任务类型。1.3.x 重要的改动如下: 架构升级:重构 worker server 移除基于 ZooKeeper 的任务队列 引入 Netty 进行 master 和 worker 间的通信 提供了三种 master 分发任务的算法:随机,轮询和资源线性加权 Worker 不再操作数据库,减轻数据库压力 新增任务类型 数据同步节点:新增了 DataX 和 Sqoop 节点,加强 DolphinScheduler 构建全流程ETL 工作流的能力 条件分支节点:提供了多个上游任务结果的复杂逻辑判断能力,根据用户自定义逻辑进行分...
- 下一篇
零基础开发 nginx 模块
推荐学习资料: nginx 开发指南: http://nginx.org/en/docs/dev/development_guide.html nginx 动态模块编译博客文章: https://www.nginx.com/blog/compiling-dynamic-modules-nginx-plus/ nginx 源码: https://github.com/nginx/nginx 本文大纲: 简要介绍 Nginx 动态模块 。 快速搭建简单 开发环境 ,拉取源码并编译 nginx 。 简要介绍 nginx 模块 源码配置与目录结构 ,建立工程框架。 简要介绍 nginx HTTP 模块结构,建立 一个 HTTP 空模块 框架代码。 编写一个简单配置文件,支持以普通用户 测试运行 nginx ,方便后续开发测试。 通过一个 hello world 示例简要介绍 Nginx 配置指令 。 简要介绍 Nginx HTTP 请求处理器 。 简要介绍 Nginx 热更新 (reload) 高级功能。 吐槽与闲聊 。 Nginx 动态模块 早期版本的 nginx 如果要扩展功能,新增代码必...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- MySQL8.0.19开启GTID主从同步CentOS8
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker安装Oracle12C,快速搭建Oracle学习环境
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS6,7,8上安装Nginx,支持https2.0的开启
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合Thymeleaf,官方推荐html解决方案