golang调用python实战

简介: # 简介 ## go-python Python提供了丰富的[C-API](https://docs.python.org/2/c-api/)。而C和Go又可以通过cgo无缝集成。所以,直接通过Golang调用libpython,就可以实现Go调Python的功能了。但是过程比较复杂,而[go-python](https://github.com/sbinet/go-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通过,说明配置成功了。

image.png

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等。

func (self *PyObject) GetAttr(attr_name *PyObject) *PyObject {
    return togo(C.PyObject_GetAttr(self.ptr, attr_name.ptr))
}

注意事项:

所有的PyObject对象使用结束,需要主动调用DecRef,通过减少引用计数的方式释放对象,否则会产生内存泄漏。

目录
相关文章
|
23天前
|
数据采集 存储 JSON
Python网络爬虫:Scrapy框架的实战应用与技巧分享
【10月更文挑战第27天】本文介绍了Python网络爬虫Scrapy框架的实战应用与技巧。首先讲解了如何创建Scrapy项目、定义爬虫、处理JSON响应、设置User-Agent和代理,以及存储爬取的数据。通过具体示例,帮助读者掌握Scrapy的核心功能和使用方法,提升数据采集效率。
66 6
|
23天前
|
设计模式 前端开发 数据库
Python Web开发:Django框架下的全栈开发实战
【10月更文挑战第27天】本文介绍了Django框架在Python Web开发中的应用,涵盖了Django与Flask等框架的比较、项目结构、模型、视图、模板和URL配置等内容,并展示了实际代码示例,帮助读者快速掌握Django全栈开发的核心技术。
124 45
|
14天前
|
数据采集 机器学习/深度学习 人工智能
Python编程入门:从基础到实战
【10月更文挑战第36天】本文将带你走进Python的世界,从基础语法出发,逐步深入到实际项目应用。我们将一起探索Python的简洁与强大,通过实例学习如何运用Python解决问题。无论你是编程新手还是希望扩展技能的老手,这篇文章都将为你提供有价值的指导和灵感。让我们一起开启Python编程之旅,用代码书写想法,创造可能。
|
16天前
|
数据库 Python
异步编程不再难!Python asyncio库实战,让你的代码流畅如丝!
在编程中,随着应用复杂度的提升,对并发和异步处理的需求日益增长。Python的asyncio库通过async和await关键字,简化了异步编程,使其变得流畅高效。本文将通过实战示例,介绍异步编程的基本概念、如何使用asyncio编写异步代码以及处理多个异步任务的方法,帮助你掌握异步编程技巧,提高代码性能。
51 4
|
15天前
|
机器学习/深度学习 数据可视化 数据处理
Python数据科学:从基础到实战
Python数据科学:从基础到实战
25 1
|
16天前
|
机器学习/深度学习 JSON API
Python编程实战:构建一个简单的天气预报应用
Python编程实战:构建一个简单的天气预报应用
33 1
|
24天前
|
数据可视化 开发者 Python
Python GUI开发:Tkinter与PyQt的实战应用与对比分析
【10月更文挑战第26天】本文介绍了Python中两种常用的GUI工具包——Tkinter和PyQt。Tkinter内置于Python标准库,适合初学者快速上手,提供基本的GUI组件和方法。PyQt基于Qt库,功能强大且灵活,适用于创建复杂的GUI应用程序。通过实战示例和对比分析,帮助开发者选择合适的工具包以满足项目需求。
76 7
|
18天前
|
前端开发 API 开发者
Python Web开发者必看!AJAX、Fetch API实战技巧,让前后端交互如丝般顺滑!
在Web开发中,前后端的高效交互是提升用户体验的关键。本文通过一个基于Flask框架的博客系统实战案例,详细介绍了如何使用AJAX和Fetch API实现不刷新页面查看评论的功能。从后端路由设置到前端请求处理,全面展示了这两种技术的应用技巧,帮助Python Web开发者提升项目质量和开发效率。
33 1
|
18天前
|
缓存 测试技术 Apache
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
35 1
|
24天前
|
数据采集 Web App开发 前端开发
Python爬虫进阶:Selenium在动态网页抓取中的实战
【10月更文挑战第26天】动态网页抓取是网络爬虫的难点,因为数据通常通过JavaScript异步加载。Selenium通过模拟浏览器行为,可以加载和执行JavaScript,从而获取动态网页的完整内容。本文通过实战案例,介绍如何使用Selenium在Python中抓取动态网页。首先安装Selenium库和浏览器驱动,然后通过示例代码展示如何抓取英国国家美术馆的图片信息。
48 6
下一篇
无影云桌面