【进阶篇】Python+Go——带大家一起另寻途径提高计算性能

2024-01-23 18:50

本文主要是介绍【进阶篇】Python+Go——带大家一起另寻途径提高计算性能,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击上方“Python爬虫与数据挖掘”,进行关注

回复“书籍”即可获赠Python从入门到进阶共10本电子书

一腔热血勤珍重,洒去犹能化碧涛。

/1 前言/

    在上一篇文章中,【基础篇】Python+Go——带大家一起另寻途径提高计算性能,我们成功的通过Python调用Go代码,并且把计算密集的交给了Go来进行计算,虽然计算的很快,但是在获取返回值时,似乎有点让人诧异,并不是我们想象的那样子。

/2 造成返回值错误的原因是什么?/

        在上一篇文章中,我们似乎都忘了一张图。

    .go文件是Go的,不多说,.so是Python调用Go的文件,那.h文件是什么???似乎很没有存在感,我们的问题出,也就出在这个.h文件中,我们打开看一下

    我们往下翻翻,会找到extern开头的声明,这个意思是将Go代码转为C代码一一对应的参数,可见,转为C的是GoInt类型,这个类型具体什么意思呢???再找找看。

    在上面其实大概可以发现,GoInt其实就是GoInt64,GoInt64的类型是long long类型,这是玩意???

    其实我们在Python中调用.so文件使用的是ctypes模块,这个是有一个对应表的。

/3 Python,ctypes , c 类型对应表/

官网地址:

https://docs.python.org/3.5/library/ctypes.html
ctypes typeC typePython type
c_bool_Boolbool (1)
c_charchar1-character  bytes object
c_wcharwchar_t1-character  string
c_bytecharint
c_ubyteunsigned charint
c_shortshortint
c_ushortunsigned shortint
c_intintint
c_uintunsigned intint
c_longlongint
c_ulongunsigned longint
c_longlong__int64 or long longint
c_ulonglongunsigned  __int64 or unsigned long longint
c_size_tsize_tint
c_ssize_tssize_t or Py_ssize_tint
c_floatfloatfloat
c_doubledoublefloat
c_longdoublelong doublefloat
c_char_pchar * (NUL  terminated)bytes object  or None
c_wchar_pwchar_t * (NUL  terminated)string or None
c_void_pvoid *int or None

    根据上述表格我们可以发现,在C中的long long类型对应的ctype类型是c_longlong。

    所以我们需要在Python将.so中的返回值改一下,不能使用系统默认的了。代码如下:

from ctypes import *
import timeclass StructPointer(Structure):# 根据查表,C中的long long,对应的ctypes 是 c_longlong# _fields_必须是[](列表)类型,里面写对应的类型,固定格式_fields_ = [("p", c_longlong,),]if __name__ == '__main__':beginTime = time.time()s = CDLL("s1.so")  # 加载s1.so文件s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式result = s.run(100000000)  # 调用Go生成的.so文件里面的run函数print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应endTime = time.time()print("耗时:", endTime - beginTime)

    再次执行:

    

    可以看到,这次Python执行的结果和Go执行结果就一个样了。继续,换个数字试试看。

    基本可以确定,这次是没问题了。

/4 如果返回的是字符串呢?/

Go代码

package mainimport ("C" //C必须导入"fmt"
)//export run
func run(n int) int{/*必须要export 函数名//是注释的意思,相当于Python中的 #我也是第一次见注释还有作用*/sum := 0for i := 0; i < n; i++ {sum += i}fmt.Println("我是Go代码,我跑完了,我的结果是:",sum)return sum
}//export speak
func speak(n int) string{return "OMG 996好累呀,难得休息一天,好好休息"
}
func main() {//main函数中什么都不要写,和包名main要对应
}

    下面一起来理解.h文件。编译之后打开.h文件如下图所示:

    可以看到,在extern的函数成了两个,但是他的返回值是GoString,继续找。

    可以发现,其实GoString就是_GoString_,继续找。

    

    这次是一个结构体,里面其实是两个值,不在是单独的long long了,那Python中的继承类也要改一下了。

下面基本同上。

完整代码如下:

from ctypes import *
import timeclass StructPointer(Structure):# 根据查表,C中的long long,对应的ctypes 是 c_longlong# _fields_必须是[](列表)类型,里面写对应的类型,固定格式_fields_ = [("p", c_longlong,),]class StrPointer(Structure):# typedef struct { const char *p; ptrdiff_t n; } _GoString_;# ptrdiff_t == long long_fields_ = [("p", c_char_p), ("n", c_longlong)]if __name__ == '__main__':beginTime = time.time()s = CDLL("s1.so")  # 加载s1.so文件s.run.restype = StructPointer # 声明.so的run函数返回值类型,固定格式result = s.run(100000798)  # 调用Go生成的.so文件里面的run函数print("result:", result.p)# 此处需要调用.p来获取值,和 _fields_对应s.speak.restype = StrPointerspeakStr = s.speak()# 返回的是字节类型,需要转字符串,返回的内容在.p中,.n是切的长度,后面会跟一些介绍,不需要speakStr = str(speakStr.p[:speakStr.n], encoding="utf-8")print("speak:",speakStr)endTime = time.time()print("耗时:", endTime - beginTime)

结果:

    可以看到,调用Go代码成功的拿到了正确的字符串返回值,如果没有 .restype = StrPointer拿到的会是什么呢?拿到会和原来的一样,一堆数字,这里就不举栗子了。

/5 小结/

    至此,基本上在Python调用Go代码上的大坑都解决了,最复杂的是返回字符串类型,查了很多相关资料才解决。

    关于返回其他类型的Python的class怎么写,我相信已经难为不到你们了,最复杂的都解决了,最简单的还不会吗?(除字符串类型以外其他_fields_都是一个字段的)

    我相信各位小伙伴学习能力还是很强的,人生苦短,Python当歌,加油,奥利给!

/6 小彩蛋/

    后台有不少小伙伴留言对Go语言感兴趣,其实我也接触Go语言不太久,这里小编开了一个新公众号【Go语言进阶学习】,主要分享Go语言相关的技术文章,感兴趣的小伙伴可以关注下,咱们一起学习。

    感谢你们的支持和鼓励,期待我们越来越好,周末愉快~

------------------- End -------------------

往期精彩文章推荐:

  • 手把手用Python教你如何发现隐藏wifi

  • 手把手教你用Python做个可视化的“剪刀石头布”小游戏

  • 一篇文章教会你用Python爬取淘宝评论数据(写在记事本)

欢迎大家点赞,留言,转发,转载,感谢大家的相伴与支持

想加入Python学习群请在后台回复【入群

万水千山总是情,点个【在看】行不行

/今日留言主题/

随便说一两句吧~~

这篇关于【进阶篇】Python+Go——带大家一起另寻途径提高计算性能的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/637199

相关文章

详解如何通过Python批量转换图片为PDF

《详解如何通过Python批量转换图片为PDF》:本文主要介绍如何基于Python+Tkinter开发的图片批量转PDF工具,可以支持批量添加图片,拖拽等操作,感兴趣的小伙伴可以参考一下... 目录1. 概述2. 功能亮点2.1 主要功能2.2 界面设计3. 使用指南3.1 运行环境3.2 使用步骤4. 核

Python 安装和配置flask, flask_cors的图文教程

《Python安装和配置flask,flask_cors的图文教程》:本文主要介绍Python安装和配置flask,flask_cors的图文教程,本文通过图文并茂的形式给大家介绍的非常详细,... 目录一.python安装:二,配置环境变量,三:检查Python安装和环境变量,四:安装flask和flas

使用Python自建轻量级的HTTP调试工具

《使用Python自建轻量级的HTTP调试工具》这篇文章主要为大家详细介绍了如何使用Python自建一个轻量级的HTTP调试工具,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录一、为什么需要自建工具二、核心功能设计三、技术选型四、分步实现五、进阶优化技巧六、使用示例七、性能对比八、扩展方向建

基于Python打造一个可视化FTP服务器

《基于Python打造一个可视化FTP服务器》在日常办公和团队协作中,文件共享是一个不可或缺的需求,所以本文将使用Python+Tkinter+pyftpdlib开发一款可视化FTP服务器,有需要的小... 目录1. 概述2. 功能介绍3. 如何使用4. 代码解析5. 运行效果6.相关源码7. 总结与展望1

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Python基础文件操作方法超详细讲解(详解版)

《Python基础文件操作方法超详细讲解(详解版)》文件就是操作系统为用户或应用程序提供的一个读写硬盘的虚拟单位,文件的核心操作就是读和写,:本文主要介绍Python基础文件操作方法超详细讲解的相... 目录一、文件操作1. 文件打开与关闭1.1 打开文件1.2 关闭文件2. 访问模式及说明二、文件读写1.

Python将博客内容html导出为Markdown格式

《Python将博客内容html导出为Markdown格式》Python将博客内容html导出为Markdown格式,通过博客url地址抓取文章,分析并提取出文章标题和内容,将内容构建成html,再转... 目录一、为什么要搞?二、准备如何搞?三、说搞咱就搞!抓取文章提取内容构建html转存markdown

Python获取中国节假日数据记录入JSON文件

《Python获取中国节假日数据记录入JSON文件》项目系统内置的日历应用为了提升用户体验,特别设置了在调休日期显示“休”的UI图标功能,那么问题是这些调休数据从哪里来呢?我尝试一种更为智能的方法:P... 目录节假日数据获取存入jsON文件节假日数据读取封装完整代码项目系统内置的日历应用为了提升用户体验,

Go标准库常见错误分析和解决办法

《Go标准库常见错误分析和解决办法》Go语言的标准库为开发者提供了丰富且高效的工具,涵盖了从网络编程到文件操作等各个方面,然而,标准库虽好,使用不当却可能适得其反,正所谓工欲善其事,必先利其器,本文将... 目录1. 使用了错误的time.Duration2. time.After导致的内存泄漏3. jsO