https://yq.aliyun.com/articles/117329

Python是时髦的机器学习御用开发语言,Golang是大红大紫的新时代后端开发语言。Python很适合让搞算法的写写模型,而Golang很适合提供API服务,两位同志都红的发紫,这里就介绍一下正确搅基的办法

原理

Python提供了丰富的C-API。而C和Go又可以通过cgo无缝集成。所以,直接通过Golang调用libpython,就可以实现Go调Python的功能了。确实没啥神奇,只要会用C调Python,马上就知道怎么用了。但问题是,如果有的选择,这个年代还有多少人愿意去裸写C和C++呢?诚心默念Golang大法好。

准备工作

  • Python :确保Python正确安装,所谓正确安装,就是在系统中能找到libpython.so(dylib),找到Python.h。一般linux直接安装python-devel,mac直接用homebrew安装就可以。
  • Golang安装:Golang不需要什么特殊的处理,能找到go即可。

安装libpython-go-binding

虽然直接用cgo调用libpython也不是不可以,但是有native-binding用起来肯定要爽的多。Github上有一个现成的Binding库go-python

 go get github.com/sbinet/go-python

如果Python安装正确,这里会自动编译并显示提示,事就这样成了。

Have a try

首先写一个测试Python脚本

import numpy
import sklearn a = 10 def b(xixi):
return xixi + "haha"

然后写一个Go脚本:

package main

import (
"github.com/sbinet/go-python"
"fmt"
) func init() {
err := python.Initialize()
if err != nil {
panic(err.Error())
}
} var PyStr = python.PyString_FromString
var GoStr = python.PyString_AS_STRING func main() {
// import hello
InsertBeforeSysPath("/Users/vonng/anaconda2/lib/python2.7/site-packages")
hello := ImportModule("/Users/vonng/Dev/go/src/gitlab.alibaba-inc.com/cplus", "hello")
fmt.Printf("[MODULE] repr(hello) = %s\n", GoStr(hello.Repr())) // print(hello.a)
a := hello.GetAttrString("a")
fmt.Printf("[VARS] a = %#v\n", python.PyInt_AsLong(a)) // print(hello.b)
b := hello.GetAttrString("b")
fmt.Printf("[FUNC] b = %#v\n", b) // args = tuple("xixi",)
bArgs := python.PyTuple_New(1)
python.PyTuple_SetItem(bArgs, 0, PyStr("xixi")) // b(*args)
res := b.Call(bArgs, python.Py_None)
fmt.Printf("[CALL] b('xixi') = %s\n", GoStr(res)) // sklearn
sklearn := hello.GetAttrString("sklearn")
skVersion := sklearn.GetAttrString("__version__")
fmt.Printf("[IMPORT] sklearn = %s\n", GoStr(sklearn.Repr()))
fmt.Printf("[IMPORT] sklearn version = %s\n", GoStr(skVersion.Repr()))
} // InsertBeforeSysPath will add given dir to python import path
func InsertBeforeSysPath(p string) string {
sysModule := python.PyImport_ImportModule("sys")
path := sysModule.GetAttrString("path")
python.PyList_Insert(path, 0, PyStr(p))
return GoStr(path.Repr())
} // ImportModule will import python module from given directory
func ImportModule(dir, name string) *python.PyObject {
sysModule := python.PyImport_ImportModule("sys") // import sys
path := sysModule.GetAttrString("path") // path = sys.path
python.PyList_Insert(path, 0, PyStr(dir)) // path.insert(0, dir)
return python.PyImport_ImportModule(name) // return __import__(name)
}

打印输出为:

repr(hello) = <module 'hello' from '/Users/vonng/Dev/go/src/gitlab.alibaba-inc.com/cplus/hello.pyc'>
a = 10
b = &python.PyObject{ptr:(*python._Ctype_struct__object)(0xe90b1b8)}
b('xixi') = xixihaha
sklearn = <module 'sklearn' from '/Users/vonng/anaconda2/lib/python2.7/site-packages/sklearn/__init__.pyc'>
sklearn version = '0.18.1'

这里简单解释一下。首先将这个脚本的路径添加到sys.path中。然后调用PyImport_ImportModule导入包

使用GetAttrString可以根据属性名获取对象的属性,相当于python中的.操作。调用Python函数可以采用Object.Call方法,,列表参数使用Tuple来构建。返回值用PyString_AS_STRING从Python字符串转换为C或Go的字符串。

更多用法可以参考Python-C API文档

但是只要有这几个API,就足够 Make python module rock & roll。充分利用Golang和Python各自的特性,构建灵活而强大的应用了。

Golang调用Python的更多相关文章

  1. Golang 调用 Python 代码

    go 中的 cgo 模块可以让 go 无缝调用 c 或者 c++ 的代码,而 python 本身就是个 c 库,自然也可以由 cgo 直接调用,前提是指定正确的编译条件,如 Python.h 头文件( ...

  2. golang和python互相调用

    http://blog.yuanzhaoyi.cn/2018/06/27/golang_python.html python3-ctypes: https://docs.python.org/3.5/ ...

  3. DES对称加密算法实现:Java,C#,Golang,Python

    数据加密标准(DES,Data Encryption Standard,简写DES)是一种采用块密码加密的对称密钥算法,加密分组长度为64位,其中8.16.24.32.40.48.56.64 等8位是 ...

  4. cpp 调用python

    在用cpp调用python时, 出现致命错误: no module named site  ,  原因解释器在搜索路径下没有找到python库.可以在调用Py_Initialize前,调用 Py_Se ...

  5. c调用python

    #include <Python.h>//python33(python2.x有几个函数不对应) /* PyImport_ImportModule 导入一个Python模块并返回它的指针 ...

  6. golang调用c++的dll库文件

    最近使用golang调用c++的dll库文件,简单了解了一下,特作此笔记:一.DLL 的编制与具体的编程语言及编译器无关 dll分com的dll和动态dll,Com组件dll:不管是何种语言写的都可以 ...

  7. linux+php+apache web调用python脚本权限问题解决方案

    lamp : linux + apache + mysql + php 在上篇随笔中linux+php+apache调用python脚本时出现的问题的根本原因是:apache运行时使用的apache用 ...

  8. linux+php+apache web调用python脚本权限问题

    lamp : linux + apache + mysql + php 在近期项目中使用 linux + apache + php调用python脚本是出现以下权限问题: build/bdist.li ...

  9. C#中调用python方法

    最近因为项目设计,有部分使用Python脚本,因此代码中需要调用python方法. 1.首先,在c#中调用python必须安装IronPython,在 http://ironpython.codepl ...

随机推荐

  1. Python进阶-XV 类和对象的命名空间 组合

    一.类和对象命名空间 1.类中可以定义两种属性 静态属性和动态属性 class Course: language = 'Chinese' # 静态属性 def __init__(self, name, ...

  2. 【LOJ2838】「JOISC 2018 Day 3」比太郎的聚会(设阈值预处理/分块)

    点此看题面 大致题意: 给你一张\(DAG\),多组询问,每次问你在起点不为某些点的前提下,到达给定终点的最大距离是多少. 设阈值 由于限制点数总和与\(n\)同阶,因此容易想到去设阈值. 对于限制点 ...

  3. 用scanf清空缓冲区 对比fflush

    fflush会将缓冲数据打印到屏幕或者输出磁盘,scanf将丢弃. 如上图.

  4. 再谈Token认证,如何快速方便获取用户信息

    前面我写了一篇<Token认证,如何快速方便获取用户信息>的文章,引起了各位读者的积极参与,除了文章中我提出的三种方式,各位读者大佬们也贡献了其他多种实现方式. 今天决定基于大家提供的思路 ...

  5. DWR日志 在log4j.xml配置

    一.日志 DWR依赖 Apache Commons Logging,可以使用log4j实现日志记录功能. 1.1 日志简介 和其他日志框架一样,当设置低等级的日志时所有高于此等级的日志也将会打印出来. ...

  6. JavaScript对象及初识面向对象

    一.对象 1.1对象是什么 对象是包含相关属性和方法的集合体 1.2什么是面向对象 面向对象仅仅是一个概念或者编程思想 通过一种叫做原型的方式来实现面向对象编程 二.创建对象 2.1自定义对象 2.1 ...

  7. 03Shell条件测试

    条件测试 Shell 条件测试 格式 1: test 条件表达式 格式 2: [ 条件表达式 ] 格式 3: [[ 条件表达式 ]] 具体参数说明可以通过 man test 进行查看 文件测试 [ 操 ...

  8. mysql派生查询必须有别名问题记录

    最近在做mysql sql兼容,原来是oracle的sql都要保证在mysql数据库运行 业务场景:原来是一个带有子查询的sql,在oracle是可以正常运行的,迁到mysql就发现报错了,报错信息如 ...

  9. win7 64bit安装redis

    win7 64bit安装redis 1 先安装redis客户端 1.下载Redis的压缩包 https://github.com/dmajkic/redis/downloads 我下载的是redis- ...

  10. MySQL数据库中查询表的所有列名

    MySQL数据库中: 查询某个数据库中某个表的所有列名 SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = ...