go、python通过go-python3传递数据

主要看在go中怎么操作

对引用的python代码初始化

import(
    "github.com/DataDog/go-python3"
)

var(
    pyTorchModule *python3.PyObject //加载python文件
	pyInitFunc *python3.PyObject //python中函数的引用
)


func initModel() {
	python3.Py_Initialize()           //初始化   
	if !python3.Py_IsInitialized() {
		fmt.Println("Error initializing the python interpreter")
		os.Exit(1)
	}

	path, _ := os.Getwd()             //获取当前路径
	pyTorchModule = ImportModule(path+"/路径", "python文件名") //引入路径下的xxx.py,函数体在下面  
	if pyTorchModule == nil {
		log.Fatalf("pyTorchModule is nil")
		os.Exit(1)
	}

	pyInitFunc = pyTorchModule.GetAttrString("python中的函数名")     //返回python中函数的一个对象。或者说是一个变量,其是python中函数的引用
	
	pyInitFunc.CallFunctionObjArgs()                                //相当于call(),通过上面的变量调用python中的该函数。
}


func ImportModule(dir, name string) *python3.PyObject { //引入python文件

	sysModule := python3.PyImport_ImportModule("sys")     //sys model,从sys模块返回对象名称。可以看作初始化语句

	path := sysModule.GetAttrString("path")        //这个函数可以在文档里查到           
 
	python3.PyList_Insert(path, 0, python3.PyUnicode_FromString(""))      //这几个也可以从python3官方文档里面找到

	python3.PyList_Insert(path, 0, python3.PyUnicode_FromString(dir))

	return python3.PyImport_ImportModule(name)
}

 然后我们就可以通过调用函数来获取返回的数据了。

go中通过 变量名.CallFunctionObjArgs() 的方法调用python3中的函数,获取python中函数的返回值

将从python中获取的数据转换为go中的浮点数组

先写一个函数,能把数据从类型*python3.Object转换为string

func pythonRepr(o *python3.PyObject) (string, error) { //python3.PyObject转string
	if o == nil {
		return "", fmt.Errorf("object is nil")
	}

	s := o.Repr()    //函数可以查到
	if s == nil {
		python3.PyErr_Clear()
		return "", fmt.Errorf("failed to call Repr object method")
	}

	defer s.DecRef()
	return python3.PyUnicode_AsUTF8(s), nil       //utf-8转Unicode
}

再写一个函数,把go中的string转成float数组

需要注意的是如果python中数组过长会出现数组中中间部分数据被逗号代替的情况

 这点需要在python用如下代码解决

numpy.set_printoptions(threshold=数组长度)

继续我们的函数

func strToFloatArry(strArry string) ([]float64, error) { //str转float数组
	var strlist, strlft, strright []string
	strlft = strings.Split(strArry, "[")      //去掉数组中的[  //切片
	strright = strings.Split(strlft[1], "]")  //去掉]
	strlist = strings.Split(strright[0], ",") //去掉,
	//log.Println(strlist)
	var floatArry []float64
	var fo float64
	for i := 0; i < len(strlist); i++ {
		var s []string
		s = strings.Split(strlist[i], " ") //数组中逗号后面有空格,需要先去除
		for j := 0; j < len(s); j++ {
			if len(s[j]) > 2 { //去掉回车
				fo, _ = strconv.ParseFloat(s[j], 64)        //这个百度就行
			}
		}
		floatArry = append(floatArry, fo)
	}
	return floatArry, nil
}

接着我们看看如何向python中传递参数并接受python中函数的返回值,最后将其变为go中的类型

func getGrad(globalW []float64) ([]float64, error) { //根据全局模型计算梯度
	runtime.LockOSThread()
	_gstate := python3.PyGILState_Ensure()       //lock()

//下面的操作是如何向python中函数中传递参数

	argArray := python3.PyList_New(len(globalW)) //将数组元素转为*python3.Object类型添加到列表中
	for i := 0; i < len(globalW); i++ {
		python3.PyList_SetItem(argArray, i, python3.PyFloat_FromDouble(globalW[i]))
	}
	var result *python3.PyObject
	result = pyPrivFunc.CallFunctionObjArgs(argArray) //调用函数,返回*python3.Object类型的梯度数组
//获得返回值后转化为go中的类型
	if result == nil {
		log.Fatalf("pyPrivFunc is nil")
	}
	strArry, _ := pythonRepr(result) //先转换为str
	if strArry == "" {
		log.Fatalf("strArry is nil")
	}

	var floatArrys []float64
	floatArrys, _ = strToFloatArry(strArry) //在str->float[]
	python3.PyGILState_Release(_gstate)     //释放锁
	return floatArrys, nil
}

在go中调用python中的函数时,我们要先把要传入的数据从go中的类型变为python的类型。思路就是建一个python中的列表(list有序)(通过python3.PyList_New() 建立),然后把要传递的参数放到列表中。

最后把这个列表变量输入到CallFunctionObjArgs()中

当python接受到go传递进来的参数的时候是一个list。

你可以通过numpy.array()变成numpy数组用于机器学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值