rust开发系列pyo3:rust与python的联动编程(上)

虾神说D 虾神说D     2023-03-10     629

关键词:

前言

Rust语言经常被人误认为是R语言,或者Ruby语言……但是做为近十年来tiobe最出人意料的编程语言,从冷门逐渐变成了明星,不过这次我们不讲Rust入门的内容,我们先来看看它一个很实用的功能——与Python的联动编程

在正式开始之前,可以先看以下几个问题:

  • 为什么要用Rust?
  • 答:Rust有很多优点,也有很多缺点,但是下面这个优点可以覆盖所有的缺点:即它能够编写出保证永远不出现内存错误的程序!!

 编程领域最头痛的问题,就是内存错误,这种错误无法排查,无法重现,随机出现,只能靠着程序员的编码能力,在编写代码的时候小心翼翼的检查以排除,所以C/C++虽然号称也可以写出内存安全的程序,但是实际上在大型程序中,几乎是一种可望不可及的理想状态。 而Rust以其特有的所有权设计思想,保证了在任何情况下的内存安全,只要编译通过,就永远不会出现内存错误。

  • 注意:不出现内存错误,不代表永远不会出现错误,而是出现任何错误,Rust都会告诉为什么会错,不会仅仅弹出一个不知所云的内存问题,让你无从下手,无从排查,也无法解决。

正文

全文一共4节,大约分为三章讲完,内容如下

  • 第一节:PyO3的简介,聊一下Python的联合开发方式,以及什么是PyO3
  • 第二节:从0开始编写一个PyO3程序,并且在Python中进行调用
  • 第三节:介绍PyO3提供的官方的脚手架,让我们如何快速的创建和编译Python扩展项目
  • 第四节:编写一系列计算密集型的插件,并且与Python原生代码和Python的JIT优化模式进行效率对比

第一节:Python扩展开发与PyO3简介

Python的优点,数不胜数,但是如果要说Python的缺点,那么下面这个应该是所有Python程序员最大的痛点:

Python有多慢呢? 下面这个是葡萄牙米尼奥大学和葡萄牙科英布拉大学联合的HAS Lab/INESC TEC(高性能计算实验室)在2020年11月发表的一篇论文,论文中对流行的编程语言进行了基准性能测试:

可以看见,无论是性能、时间、还是内存消耗,Python都几乎是倒数,特别是在计算性能和消耗时间上,几乎只有C、Rust、C++这三者的七十分之一!

当然,这里说个题外话,高性能有若干前提要求,不是说Python本身慢,写出来的东西就一定很慢,Python有大量优化方式和手段,例如静态编译(JIT),或者使用numpy这种高性能包,都能够大大提升Python的性能。

另外,程序运行的模式,也会对代码编写和架构有很大的影响,一般来说,在IO(数据)密集型运算上,管你用什么语言,性能都只能被数据吞吐这块短板所拖累……今天不谈这些内容,今天我们主要就针对计算(CPU)密集型运算这种与编程语言和编译器有密切关系的方式。

所以,抛开一切其他条件不谈,我们的诉求,就是一句话:

速度!
速度!!
还TM是速度!!

如果说Python原生的速度,就像体重和身高一样的正方体肥仔虾一样,从小学开始到大学毕业,体育考试中的长跑就从来没有及格过,基本上等于放弃治疗的话,如何最简单的提速呢?

请圣言

人和动物的区别在于,人能够创造工具,动物可以使用工具,但不能创造工具。

——卡尔 马克思

回过来,肥宅Py如何利用工具,变成狂飙Py呢?这就要从Python的扩展开发模式来看了:

首先,我们经常说的,Python,实际上指的是CPython,即C语言实现的Python,广义上,Python还有Jython和IronPython这两个版本,分别是Java的Python实现和.Net的Python实现,不过后面这两个东西,已经很久没有更新了,属于死了但是没有完全死的状态,基本上我们可以忽略……

所以,现在我们说的Python,事实上指的就是CPython,所以可以认为Python的底层就是C语言,那么官方提供的Python的扩展方式,就是用C语言来编写扩展模块(Python的标准库,绝大部分都是C语言开发的,C++属于蹭C语言的框架)。

其他语言如果扩展Python,只能通过如RPC(远程过程调用)这种方式,或者语言扩展桥接绑定的方式来实现,这两种模式就不能叫做扩展开发了。

那么Rust对于Python的扩展开发,又是哪一种方式呢? 答案是基于C语言的桥接模式。Rust可以直接继承C/C++的所有工具和库,也能够支持把自己编译成与C一样的动态链接库,所以我们可以把PyO3看成是Rust绑定C语言的一种扩展方式,也就是说,Rust PyO3写出来的扩展,与原生C写出来的扩展,对于Python是完全一样的。

PyO3开发出来的扩展模块,有如下特点:

  1. 开发出来的扩展模块,运行于Python同进程中,所以可以直接在Python语言环境中导入、调用、监控和管理。
  2. 可以在Rust中编写的、编译好的可执行程序中,调用和动态执行Python代码的能力,并且提供两种语言之间的控制与数据交互能力。

第二节:Python扩展开发与PyO3简介

首先还是用Rust的cargo包管理器去创建一个lib工程,这一步没啥说的。

如果你是一位从来没有接触过Rust的同学,那么可以先不必深究这些细节,建议直接看后面的结果。 然后就采用量子学习法即可:

  • 点赞就是看过了

  • 收藏就是学会了

  • 转发就是融会贯通了

然后在crates.io网站上,找到PyO3包,并且把它添加到配置文件里面去。当然,如果你很熟练了,也不用去网站上找,直接添加也行(建议去网站上,查找最新的版本号。)

crates.io是Rust的一个包管理仓库网站,类似于Python的pypi。

添加配置项,注意,需要有两个必选的配置项:

crate-type = ["cdylib"]

这个表示编译时候使用的c标准的动态库 Python的底层就是用c语言写的,必须是c标准库,Python才能导入

pyo3 = version = "0.18.1", features = ["extension-module"]

给工程添加最新的pyo3版本,并且设置特性为扩展模块,这个版本号一般我都选择最新的,所以在添加前都回去crates.io网站上查阅一下,不过你也可以通过

cargo add pyo3

这个命令来添加

之后,就可以编写Rust的功能实现代码了,主要需要编写两个部分: 

  1. 编写逻辑业务实现部分,我们这里实现一个say hello的功能,也就是用户输入一个用户名,这里输出一个问候,并且告诉他,这个问候来自Rust编写的后台扩展。

如果需要直接封装成Python可以调用的方法,需要在前面加#[pyfunction]这个属性,表示这个方法将对外暴露,并且被直接封装成Python可以调用的方法。

  1. 可以写一个测试方法,因为Rust是一种编译执行的语言,所以要执行一个方法必须要有main函数,如果不想添加main.rs和main函数的话,可以写一个测试方法,在cargo里面测试用。
  2. 把写好的Python扩展方法,封装到Python模块声明里面去,写一个Python模块声明方法。

#[pymodule]属性表示这个模块里面,要封装暴露哪些方法出来,而且还声明了是否有输入和输出参数。

全部写完之后,可以通过cargo test测试一下,方法是否能够正常执行,之后就可以打包封装了。

直接输入命令:

cargo build --release

对工程进行编译,在这个编译的过程中,cargo编译器会从网络上拉下一些依赖,然后在本地直接编译好,但是这个过程比较慢……特别是大型工程,一次编译可能需要几十分钟之久。

不过好在我们这个工程中没有什么需要依赖的大型库,所以编译还算快,在我本机上,11秒就编译好了。

之后,在工程的/target/release目录下面,会生成一个叫做pyo3demo.dll的动态链接库文件,这个就是windows平台下面的Python扩展模块,如果在Linux下面,会编程成so文件。

因为我们这里是一个裸奔的版本,所以后面还需要手动改一下名字,在Python中,扩展库的的后缀名都是pyd,所以需要我们手动把pyo3demo.dll改名为pyo3demo.pyd。

之后把这个pyd文件,拷贝到你的Python包索引环境的目录下面去,就可以了,最简单的就是直接拷贝到你py文件同目录下。

然后按照Python开发的一般模式,import这个包,然后直接使用即可:

如果输出的内容是我们测试中预想一样的,那就表示成功了。

最后,给出这个say hello应用中可能出现的一些场景问题:

打完收工。

最后,本工程的全部源码,在我gitee仓库如下位置:

博客: 博客文章,方便发文 - Gitee.com

注意: 我的代码里面还有后续的测试的内容,特别包含了polars包,所以编译起来比较慢,也特别大……

rust开发系列pyo3:rust与python的联动编程(下)

第四节:RustPyO3与Python原生代码的效率对比今天我们通过一系列代码和算法,来对比一下RustPyO3编写的扩展与原生Python代码之间的效率。对比的算法如下:大浮点数运算,主要就测试浮点数的乘法和除法,这种... 查看详情

rust拓展包是什么内容

参考技术A使用PyO3和rust-cpython实现的rustpython扩展的setuptools帮助程序。编译和分发用rust编写的python扩展就像它们是用c写成的。设置首先,您需要创建一组文件:设置.pyfromsetuptoolsimportsetupfromsetuptools_rustimportBinding,RustExtensionsetup(name... 查看详情

rust实战系列-rust介绍

Rust实战系列第一部分,主要包括Rust的基本介绍。Rust实战系列第一部分,主要包括Rust的基本介绍。 查看详情

c++&rust对比c++学习和运用rust语言系列文章

接下来,会出一系列文章,通过比较C++与Rust的异同点,更好的学习r和运用Rust语言! 查看详情

c++&rust对比c++学习和运用rust语言系列文章

接下来,会出一系列文章,通过比较C++与Rust的异同点,更好的学习r和运用Rust语言! 查看详情

c++&rust对比c++学习和运用rust语言系列文章

接下来,会出一系列文章,通过比较C++与Rust的异同点,更好的学习r和运用Rust语言! 查看详情

c++&rust对比c++学习和运用rust语言系列文章

接下来,会出一系列文章,通过比较C++与Rust的异同点,更好的学习r和运用Rust语言! 查看详情

Rust 是不是具有与 Python 的列表理解语法等价的功能?

】Rust是不是具有与Python的列表理解语法等价的功能?【英文标题】:DoesRusthaveanequivalenttoPython\'slistcomprehensionsyntax?Rust是否具有与Python的列表理解语法等价的功能?【发布时间】:2017-12-3004:19:15【问题描述】:Python列表推导真的... 查看详情

databend源码阅读系列:开篇

...同学的关注。Databend使用了Rust编程语言。为了吸引更多的开发者,特别是没有Rust开发经验的新同志,我们设计了Rust相关课程,同时建立了多个Rust兴趣小组。Databend在issue中还引入了“GoodFirstissue”的label来引导社区新同学参与第... 查看详情

.net番外篇rust环境搭建+基础开发入门+rust与.net6c++的基础运算性能比较

...来就是爽。缘起:之前打算一些新的产品或者新的要开发的东西,由于没有历史包袱,就想重新选型一下,在.NET平台(C#语言)、Golang、Rust里面进行 查看详情

揭秘前端眼中的rust!

导语 | 本文推选自腾讯云开发者社区-【技思广益·腾讯技术人原创集】专栏。该专栏是腾讯云开发者社区为腾讯技术人与广泛开发者打造的分享交流窗口。栏目邀约腾讯技术人分享原创的技术积淀,与广泛开发者互启迪共... 查看详情

揭秘前端眼中的rust!

导语 | 本文推选自腾讯云开发者社区-【技思广益·腾讯技术人原创集】专栏。该专栏是腾讯云开发者社区为腾讯技术人与广泛开发者打造的分享交流窗口。栏目邀约腾讯技术人分享原创的技术积淀,与广泛开发者互启迪共... 查看详情

用rust开发linux,可行吗?(代码片段)

...原生领域已经稳定占据了C位,那么让Rust更进一步去开发操作系统的内核,就成为很多Rust粉丝心中的终极梦想,而Rust官方也一直有想法使Rust语 查看详情

rust备忘清单_开发速查表分享

Rust备忘清单IT宝库整理的Rust开发速查参考备忘单,旨在为编写基本语法和方法提供帮助。入门,为开发人员分享快速参考备忘单。Rust是一门系统编程语言,专注于安全,尤其是并发安全,支持函数式和命令式以及泛型等编程范... 查看详情

十年python程序员,初次尝试rust:“非常优秀!”

摘要:Python和Rust,都是近几年深受开发者喜爱的编程语言,那么作为一个拥有十年Python编程经验的开发者来说,初次尝试Rust会有怎样的感受呢?链接:https://karimjedda.com/carefully-exploring-rust/声明:本文... 查看详情

rust日报2022-02-23官方博客:rust编译器的2022雄心

PopOS正在与Relm4配合,以帮助用Rust在PopOS上开发GTK程序PopOS是要开发RustLinux发行版的System76的Linux发行版,现在正致力于和Relm4合作,帮助用Rust在PopOS上更容易地开发GTK程序。Relm4是基于GTK上层的一套框架,提供类Elm的编程模式。Link... 查看详情

2023年rust发展如何?

...首次发布以来,Rust一直在快速发展,吸引了越来越多的开发者加入其社区。Rust语言的设计目标是提供一种安全、并发和实用的语言,它可以满足系统编程的需求,同时也适用于其他领域。2.Rust在2022年的发展趋势在2022年,Rust的... 查看详情

rust学习内存安全探秘:变量的所有权引用与借用

作者:京东零售周凯一.前言Rust语言由Mozilla开发,最早发布于2014年9月,是一种高效、可靠的通用高级语言。其高效不仅限于开发效率,它的执行效率也是令人称赞的,是一种少有的兼顾开发效率和执行效率的语言。Rust语言具备... 查看详情