关于jquery:golang调用python实战

6次阅读

共计 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 机制所须要的一些辅助字段等,所以说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,通过缩小援用计数的形式开释对象,否则会产生内存透露。

原文链接
本文为阿里云原创内容,未经容许不得转载。

正文完
 0