qiniu/py是一个在golang中复用旧的python代码的工具框架,它充许程序员将本地可执行的python拷贝至go源码中,给go代码调用。目的很简单,就是为了复用业已成熟的python类库,以go语言为主,保持语言使用的简洁性。
py为许式伟七牛团队作品。许式伟是力挺go语言的编程大牛。江湖人称七牛有七牛,但很少有人知道是哪七牛。
1,运行示例
go get github.com/qiniu/py
vim py-demo.go
package main
import (
"fmt"
"github.com/qiniu/log"
"github.com/qiniu/py"
)
// -------------------------------------------------------------------
type FooModule struct {
}
func (r *FooModule) Py_bar(args *py.Tuple) (ret *py.Base, err error) {
var i int
var s string
err = py.Parse(args, &i, &s)
if err != nil {
return
}
fmt.Println("call foo.bar:", i, s)
return py.IncNone(), nil
}
func (r *FooModule) Py_bar2(args *py.Tuple) (ret *py.Base, err error) {
var i int
var s []string
err = py.ParseV(args, &i, &s)
if err != nil {
return
}
fmt.Println("call foo.bar2:", i, s)
return py.IncNone(), nil
}
// -------------------------------------------------------------------
const pyCode = `
import foo
foo.bar(1, 'Hello')
foo.bar2(1, 'Hello', 'world!')
`
func main() {
gomod, err := py.NewGoModule("foo", "", new(FooModule))
if err != nil {
log.Fatal("NewGoModule failed:", err)
}
defer gomod.Decref()
code, err := py.Compile(pyCode, "", py.FileInput)
if err != nil {
log.Fatal("Compile failed:", err)
}
defer code.Decref()
mod, err := py.ExecCodeModule("test", code.Obj())
if err != nil {
log.Fatal("ExecCodeModule failed:", err)
}
defer mod.Decref()
}
// -------------------------------------------------------------------
go run py-demo.go
在mac运行,我的机器提示缺少pkgconfig,于是使用brew安装
(brew是mac的软件包管理工具,安装brew的命令:ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
)
brew install pkgconfig
还不行,提示我没有python 2.7,于是又安装(其实有python):
brew install python
这一步时间较长,耐心干别的事。回来继续操作,还不行,提示:
cgo argument has Go pointer to Go pointer
自golang 1.6,添加了Go和Cgo之间传递指针的限制,见:commit
这个特性默认开启,可以通过GODEBUG=cgocheck=0关闭
继续:
GODEBUG=cgocheck=0 go run py-demo.go
终于可以运行了:
附源码与执行文件(mac):链接: https://pan.baidu.com/s/1hrYDhVQ 密码: nnxm
写程序做项目,被一个问题卡住,死活都解不开,这个时候就显现出经验的价值了。知识与经验可以让团队、项目节省时间,提前上线。知识服务,在程序编程这个领域不是空谈。
---
网上有人总结说,七牛py有三个缺陷:
1、 在golang中无法以函数名直接调用python代码中的单个函数。
2、python 可以调用 golang 的函数,但golang的返回值,python无法取得。
3、如果在python调用golang的方法中包含:全局chan ,如果这个golang函数 <- 写入数据将导致block。(不能在Py_开头的函数中向全局的chan写内容)
其实无所谓,看是什么需要,复用大多数python类库已经可以了。所有框架都是有缺点的,有一分用,但有一分缺陷。用就可以了,有用就好。
既然提到了python,给不熟悉的同学推荐一份简明教程:http://www.kuqin.com/abyteofpython_cn/
--
关注微信公众号【哲学李论】,回复“Go语言后台编程问题集锦”,可以查看该系列的所有文章: