Pyo3学习,尝试对Python加速

PyO3:一个Rust与Python无缝交互的工具,用Rust打造高性能Python应用 无论你想用 Rust 编写 Python 模块,还是将 Python 集成到 Rust 程序中,PyO3 都能满足你的需求。如果你需要在 Rust 程序中使用 Python 的库或功能,PyO3 可以让你轻松实现。例如,你可以使用 Python 的数据分析库进行数据处理,然后将结果返回给你的 Rust 程序。如果你需要用 Rust 的性能优势来加速你的 Python 代码,PyO3 是你最好的选择。使用 PyO3,你可以在 Rust 程序中嵌入 Python 解释器,并调用 Python 代码。 阅读详情

PYO3是Python -> Rust / Rust-> Python的第三方库

参考的官方地址: https://pyo3.rs/main/module.html

创建Python模块(打包)

利用pymodule宏创建模块:

use pyo3::prelude::*;

// 创建一个功能
#[pyfunction]
fn double(x: usize) -> usize {
    x * 2
}

/// 这个功能以函数的形式拓展在模块当中
#[pymodule]
fn my_extension(py: Python<'_>, m: &PyModule) -> PyResult<()> {
    // 拓展的函数名字就叫做double, m是拓展的自带参数
    m.add_function(wrap_pyfunction!(double, m)?)?;
    Ok(())
}
// 我们可以看一下这个过程宏的源码
#[proc_macro_attribute]
pub fn pymodule(args: TokenStream, input: TokenStream) -> TokenStream {
    parse_macro_input!(args as Nothing);
	// 整体还是可以理解的,把我们输入的函数转换为ast, 并看看ast语法便以上有没有错误
    let mut ast = parse_macro_input!(input as syn::ItemFn);
    let options = match PyModuleOptions::from_attrs(&mut ast.attrs) {
        Ok(options) => options,
        Err(e) => return e.into_compile_error().into(),
    };

    if let Err(err) = process_functions_in_module(&mut ast) {
        return err.into_compile_error().into();
    }
	
    // 贴心的位子自动写注释,不过我这里的注释打爆出来一直都是None, 不知道啥情况。
    let doc = get_doc(&ast.attrs, None);
	// 没有问题就把doc文档(我们Pycharm查看库的时候看到的内玩应一同打包。)
    let expanded = pymodule_impl(&ast.sig.ident, options, doc, &ast.vis);

    quote!(
        #ast
        #expanded
    )
    .into()
}

Pymodule肯定不止能打包函数,还可以打包类的,后面的部分会讲到。

Python模块可以分文件创建相应的内容,不过这一块太简单了,参考官网就可以了。

Python函数

该#[pyfunction]属性用于从 Rust 函数定义 Python 函数。还是一样的,我们随便看一下源码:

// 相较于上面的module, 这个宏就简单很多,当然我不可能取深究最低层的代码,太浪费时间了
#[proc_macro_attribute]
pub fn pyfunction(attr: TokenStream, input: TokenStream) -> TokenStream {
    // 把我们的Fn 强制转换成PyFuction类型,然后把就强转
    let mut ast = parse_macro_input!(input as syn::ItemFn);
    let options = parse_macro_input!(attr as PyFunctionOptions);

    let expanded = build_py_function(&mut ast, options).unwrap_or_compile_error();
	
    // 这个宏强转TokenStream
    quote!(
        #ast
        #expanded
    )
    .into()
}

根据官方文档,我们可以字此基础上做如下操作:

// 重命名
#[pyfunction]
#[pyo3(name = "test2")]
pub fn b(){
    println!("Hello I am Lihua")
}

import rust_give_python as ru
if __name__ == '__main__':
    ru.test2()
Hello I am Lihua

由于Rust的多线程是真正的多线程,所以我们很想使用类似于闭包的方法让Rust中运行Python的代码,但是比较可惜的是目前, Rust 中的 s 和 Python 中的 callable之间没有转换。这个想法目前还是不可行的,真的是麻中麻。

Python 类

除了函数,我们有时候还需要定义类来更进一步的对Python进行提速封装。官网是这么说的:公开了一组由 Rust 的 proc 宏系统提供支持的属性,用于将 Python 类定义为 Rust 结构。

这一节的宏更类似与修饰器,问题不大,我们直接开冲

#[Pyclass]

定义类数据部分结构的宏。一般选择用结构体定义,也可以接受枚举类型,其他类型不行:

#[proc_macro_attribute]
pub fn pyclass(attr: TokenStream, input: TokenStream) -> TokenStream {
    use syn::Item;
    // 分语法解析分词并查看有没有错误
    let item = parse_macro_input!(input as Item);
    match item {
        // 这两个地方用的不同语法分析函数,我把struct分析函数放在了下面
        Item::Struct(struct_) => pyclass_impl(attr, struct_, methods_type()),
        Item::Enum(enum_) => pyclass_enum_impl(attr, enum_, methods_type()),
        unsupported => {
            syn::Error::new_spanned(unsupported, "#[pyclass] only supports structs and enums.")
                .into_compile_error()
                .into()
        }
    }
}
// struct的分析函数
fn pyclass_impl(
    attrs: TokenStream,
    mut ast: syn::ItemStruct,
    methods_type: PyClassMethodsType,
) -> TokenStream {
    // 用这个宏价检查结构参数语法
    let args = parse_macro_input!(attrs with PyClassArgs::parse_stuct_args);
    // 强转py_class
    let expanded = build_py_class(&mut ast, args, methods_type).unwrap_or_compile_error();
	// 打包
    quote!(
        #ast
        #expanded
    )
    .into()
}
#[pymethods]

类肯定不能只有结构体,还应该有相应的method方法(类里面的执行代码不叫函数叫方法!!)。来看源码:

pub fn pymethods(_: TokenStream, input: TokenStream) -> TokenStream {
    // 编译的时候给一个feature变量? 主要是看拓展的方法是否为多个
    // 之后用pymethods_impl去做语法转换
    let methods_type = if cfg!(feature = "multiple-pymethods") {
        PyClassMethodsType::Inventory
    } else {
        PyClassMethodsType::Specialization
    };
    pymethods_impl(input, methods_type)
}

// 在这里就直接利用quote宏打包了,expand使用的构造pymethod的方法。针对源码非常感兴趣的化自己去看呗
fn pymethods_impl(input: TokenStream, methods_type: PyClassMethodsType) -> TokenStream {
    let mut ast = parse_macro_input!(input as syn::ItemImpl);
    let expanded = build_py_methods(&mut ast, methods_type).unwrap_or_compile_error();

    quote!(
        #ast
        #expanded
    )
    .into()
}
  • #[new]

    有类就要有实例化嘛, 还有一些常见的方法,不是说你放了Pymodule就能调用了。Rust 方法名称在这里并不重要,我们不是定义完方法就直接可以用Rust的方法名称调用的 所以Rust为我们提供了一些服务名称,首先就是我们实例化的__new__方法.

    #[pyclass]
    pub struct test_class{
        pub name: String,
        pub id:i32,
    }
    #[pymethods]
    impl test_class {
        #[new]    	//我们新建一个new方法让类可以在Python中被创建。
        fn new() -> test_class{
            test_class{name: String::from("hello"), id:1}
        }
    }
    
    import rust_give_python as ru
    if __name__ == '__main__':
        ru.test_class()
    

    #[new]方法必须返回T: Into<PyClassInitializer<Self>>or PyResult<T> where T: Into<PyClassInitializer<Self>>。不过我们在构造new的时候一般返回对象本身嘛,不过这也是后话了

  • [#pyo3(get,set,name = “*”)]

    对于我们定义好的类来说,虽然他内部的属性已经有了定义的值/ 分配的内存,可是我们刚刚也说过名字毫无意义。我们根本不值到它真正的属性名字叫什么,**而且没有实现__dict__魔法方法你找不到的,,**所以我们就需要用pyo3定义get, set简单的查值和设置值。我们还可以使用name字段位属性重新设定名字

    #[pyclass]
    pub struct test_class{
        #[pyo3(get,set)]
        pub name: String,
        #[pyo3(get,name="iddd")]
        pub id:i32,
    }
    
    import rust_give_python as ru
    if __name__ == '__main__':
        a = ru.test_class()
        print(a.name)
        a.name = "Hello"
        print(a.iddd)
    	// 要想改变值必须要有set才可以
        try:
            a.iddd = 10
            print("set ok")
            print(a.iddd)
        except:
            print("can't set a.iddd")
    
    hello
    1
    can't set a.iddd
    
  • 同时上面的表达等价位#[getter] #[setter]

    pub struct test_class{
        #[pyo3(get,set)]
        pub name: String,
        #[pyo3(get,name="iddd")]
        pub id:i32,
        pub year:i32
    }
    #[pymethods]
    impl test_class {
        #[new]
        fn new() -> test_class{
            test_class{name: String::from("hello"), id:1,year:80}
        }
        #[getter]
        fn get_year(&self) ->PyResult<i32>{
            Ok(self.year)
        }
        #[setter]
        fn set_year(&mut self, value:i32){
            self.year = value;
        }
        
    import rust_give_python as ru
    if __name__ == '__main__':
        a = ru.test_class()
        a.year = 10
        print(a.year)
    10
    
#[classmethod]

除了参数之外,类还需要提供其他方法。classmethod为自定义类创建类方法, 不过我一般不咋用,官网的例子在这:

// 这个例子真的看起来没啥用就不演示
#[pymethods]
impl MyClass {
    #[classmethod]
    fn cls_method(cls: &PyType) -> PyResult<i32> {
        Ok(10)
    }
}
用Rust为Python编写软件包,PyO3与Maturin的快速使用 PyO3快速实现Rust编写Python包,加速Python代码性能。 阅读详情

相关推荐

Rust + Python 协作实战:PyO3 高性能扩展开发指南

Python 作为胶水语言在数据科学与工程中广受欢迎,但其 GIL 限制、运行时开销和内存安全性问题,在 CPU 密集计算、正则解析、高并发状态管理及系统级 IO 场景下常引发性能瓶颈与稳定性风险。Rust 凭借零成本抽象、内存安全保证和无 GC 并发模型,成为 Python 原生加速的理想协作者——尤其通过 PyO3 实现无缝绑定。它不替代 Python,而是以‘精准外科手术’方式加固关键路径:支持类型安全的函数暴露、自动生命周期管理、跨平台 wheel 构建,并天然兼容 NumPy、asyncio 等生

weixin_30784501的博客 362

PyO3:让 Python 爽翻天

PyO3 作为 Python 与 Rust 之间的协作桥梁,完美结合了 Python 的“开发便捷性”与 Rust 的“高性能、内存安全”特性

码刀攻城 1538

Rust-Python互操作实战:零成本抽象提升性能与稳定性

Rust-Python互操作是一种融合两种语言优势的现代系统集成范式,其核心在于利用Rust的内存安全与零成本抽象能力,弥补Python在CPU密集、低延迟及高并发场景下的GIL限制与ABI不稳定性。技术原理上,通过PyO3等绑定工具实现无缝类型映射与生命周期管理,避免C扩展的手动引用计数和Cython的语法幻觉,在保障安全性的同时达成接近原生C的执行效率。该方案显著提升数据处理、异步I/O、数值计算与密码学等关键模块的可预测性与生产稳定性,特别适用于Pandas加速、FastAPI后端优化及FIPS合规加

tyygming的专栏 354

探索PyO3:Rust与Python的强强联手

探索PyO3:Rust与Python的强强联手 【免费下载链接】pyo3 Rust bindings for the Python interpreter 项目地址: https://gitcode.com/gh_mirrors/py/pyo3 ...

gitblog_00055的博客 1101

Rust与Python协同开发实战:性能、安全与嵌入式优化

Rust与Python协同开发是一种面向生产环境的混合编程范式,其核心在于利用Rust的内存安全、零成本抽象和无锁并发能力,弥补Python在高并发、低延迟、系统调用和资源受限场景下的固有局限。该模式不追求语言替代,而强调分层协作:Python承担业务编排、数据科学生态与快速迭代,Rust专注性能敏感执行层。技术价值体现在显著降低P99延迟(实测下降81%)、消除段错误与内存泄漏、支持静态链接嵌入式部署(二进制仅1.2MB),并提升故障可追溯性。典型应用场景包括NumPy瓶颈加速、异步HTTP服务卸载、ct

weixin_34405354的博客 392

《Rust 实战指南》第 11 章:越界——Unsafe Rust 与混合编程实战

本章的内容是很多 Java/Python 开发者选择 Rust 的直接动力——互操作性。对于 Python 开发者,Rust 是编写高性能扩展(Extension Modules)的神器;对于 Java 开发者,Rust 是比 C++ 更安全的 JNI 替代方案。本章将带你走出 Rust 的“安全围墙”,去连接广阔的外部世界。

撸码猿的博客 926

探索异步编程新天地:PyO3 Asyncio的奇妙之旅

探索异步编程新天地:PyO3 Asyncio的奇妙之旅 pyo3-asyncio 项目地址: https://gitcode.com/gh_mirrors/py/pyo3-asyncio 在这个快速发展的技...

gitblog_00070的博客 1258

通过 PyO3 构建 Python 与 Rust 的无缝桥梁

通过 PyO3,你可以轻松地将 Rust 编写的高性能代码嵌入到 Python 中,并在 Python 中直接使用 Rust 编写的功能。这种集成方式带来了以下好处:

s13166803785的博客 225

C FFI vs PyO3:在 Rust 中嵌入 C++ 推理核心的取舍

在构建工业级高吞吐 AI 推理底座时,果断采用原生 C FFI / cxx 消除中间一切冗余解释层,是释放硬件极限性能的不二法门。

2301_81410839的博客 2061

Python-PyO3Python解释器的Rust绑定

PyO3: Python解释器的Rust绑定

Canoe CAPL TCP通信避坑指南:从OnTcpConnect回调不触发到Socket句柄管理

本文详细解析了Canoe CAPL中TCP通信的常见问题与解决方案,包括OnTcpConnect回调不触发的三大原因、Socket句柄管理的内存泄漏风险、数据发送截断规则等。通过实战案例和代码示例,帮助开发者规避TCP通信中的典型陷阱,提升车载网络测试的稳定性和可靠性。

weixin_26976635的博客 358

应用-使用Rust加速Python的最简单方法

然而,如果你只是想快速尝试Rust扩展,打包和集成样板代码可能会成为障碍:每增加一点摩擦都会阻碍你进行实验,看看Rust是否真的能带来帮助。的用武之地,它是一个库,使得独立的Rust文件可以轻松地在Python中导入(目前仅支持Linux和macOS)。当你编译Rust代码时,有不同的编译配置文件,它们以不同的方式编译。确实可以扩展到完整的Rust项目,但在这一点上,它的优势下降,切换到更明确的构建系统可能更好。这不是你最终打包库或应用程序时所需的,但我们的用例是原型设计,无论如何你都需要一个编译器。

liluo0815481的博客 1111

如何编译RustDesk(Unbuntu 和Android版本)

备注:官方文档上,一边都是基于sciter,这个在后面已经不建议使用了,但是依然可以编译刚开始的时候看官方的文档,涉及的东西比较多,也搞的一头雾水,通过B站上一个视频,可以通过CI/CD来编译,以及act本地试试(最终放弃,大概需要下载大几十G的容器下来)。最终总算明确了方向,可以用自动化流水线来编译。直接看CI/CD的脚本文件文件在.github/workflows目录下,重点研究 bridge.yml 和flutter-build.yml 这两个文件。

lvronglee的专栏 2548

2024三掌柜赠书活动第十五期:Python高效编程——基于Rust语言

Python高效编程——基于Rust语言》详细阐述了基于Rust语言的Python高效编程,主要包括从Python的角度认识Rust、使用Rust构建代码、理解并发性、在Python中构建pip模块、为pip模块创建Rust接口、在Rust中使用Python对象、在Rust中使用Python模块、在Rust中构建端到端Python模块、构建Python Flask应用程序、将Rust注入Python Flask应用程序、集成Rust的**实践等内容。本书将涉及一些高级主题,如元类,但不是必不可少的。

全沾软贱开发攻城狮 1万+

无源低通滤波器

无源RC滤波器“滤除”不需要的信号,因为它们分离并允许仅通过其频率的正弦输入信号,最简单的是无源低通滤波器网络。在低频应用(高达100kHz)中,无源滤波器通常使用简单的RC(电阻-电容)网络构建,而高频滤波器(高于100kHz)通常由RLC(电阻-电感-电容)元件制成。无源滤波器由电阻器、电容器和电感器等无源元件组成,没有放大元件(晶体管、运算放大器等),因此没有信号增益,因此它们的输出电平始终小于输入。滤波器是根据它们允许通过它们的信号的频率范围来命名的,同时阻挡或“衰减”其余部分。

weixin_44448586的博客 1万+

SAP VC 可配置物料超级BOM简介

在有些业务中比如:汽车、笔记本、电脑、电梯等产品中,其中组成产品的型号个框架是确认的 ,但是框架内部的BOM是可变的,在客户下销售订单的时候,选取对应的组件 ,让后通过MRP的计算优生产线对这样的销售订单提供生产。这个时候我们需要选择我们需要的内存和硬盘的型号,还记得我们前面创建的特征值对应的吗,A对应的8G、B对应16G、X对应1T硬盘、Y对应2T硬盘,这里我们填写对应的值,我们这里选择16G的内存和2T的硬盘,B和Y。3、当我们选择了可配置物料的生产模式时,基本上就选择了按单生产的生产模式了。

我小时候很黑的博客 1万+

GIL-Free Python并发仅剩最后1%难题:我们用37小时逆向分析PyO3内存模型,找到共享引用计数的终极解法

破解Python无锁GIL环境下并发瓶颈,提出基于PyO3的共享引用计数方案。适用于CPU密集型Rust-Python混合编程场景,实现零GIL、无锁、内存安全的并发模型。含完整实战案例与性能对比数据,值得收藏。

CodeVibe的博客 240

RobotFramework二次开发——实时日志

背景基于RobotFramework的二次开发,少不了要打印实时日志出来,比如广泛应用的工具ride中,在执行用例时会把执行过程中的log全部打印出来,如果二次开发的时候,执行用例只能静默等待执行完毕,那只能算是一个半成品。结果在最后,不想看过程的可以直接跳到最后思路RobotFramework的日志有好几种,一个是执行后的log文件,这个文件可以作为数据留存,但是没办法实时获取,因为文件是在执行完

点点寒彬的博客 1万+

Termux上玩转Jupyter Notebook:手把手解决Rust环境下的maturin报错(附清华源加速)

本文详细指导在Termux上配置支持Rust扩展的Jupyter Notebook环境,特别针对maturin编译过程中的典型报错提供解决方案。涵盖环境初始化、Rust工具链配置、maturin编译问题排查及Jupyter生态系统部署,帮助开发者在移动设备上高效搭建开发环境。

weixin_30745553的博客 612

第21章—技术管理篇(上):身为技术人该怎样带好团队并做好管理者

上节讲了职业规划和学习提升这两个话题,随着职业规划的不断落地,或者自己能力的不断提升,大家也会逐渐被提拔成“职级更高”的人。企业规模扩张时,员工数量也会变多,意味着Boss需要更多的人来辅助管理,而管理者会从外部招聘吗?也许会,但大多企业更喜欢从内部选拔,毕竟人的天性更希望找的人值得信赖。此时,一些能力不错、做事靠谱的老员工,就会被“赶上”管理者的位子。作管理不难,但想要“”就需要一定情商。

运维老生常谈 1366

高通 vs MTK vs 海思:三大平台 ISP 架构横向对比与实战差异分析

随着移动影像能力成为智能终端差异化竞争的核心维度,ISP(Image Signal Processor)架构日益重要。高通、MTK、海思三大 SoC 厂商在 ISP 设计上各具特色,不仅在图像处理链路、模块集成度、算法加速路径等方面存在显著差异,同时也决定了终端厂商在成像质量、调试复杂度与扩展能力上的实际表现。本文将基于真实平台项目经验,横向对比三大主流平台的 ISP 架构关键指标,系统分析其在实际开发过程中的能力边界、工程成本与调优空间,帮助工程师更精准地进行平台选型与优化策略制定。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3934

Rust + Python 互操作实战:用 PyO3 实现零拷贝高性能扩展

Python 作为胶水语言生态强大但受制于 GIL 和解释执行开销,而 Rust 以零成本抽象、内存安全与无 GC 延迟成为理想性能补足方案。其核心价值在于通过原生 ABI 绑定实现跨语言零拷贝数据共享,尤其在 numpy 数组处理、高频计算和低延迟服务中显著提升 P99 稳定性。PyO3 不仅提供函数级调用,更支持将 Rust 结构体编译为原生 Python 类,深度集成类型系统、GC 生命周期与魔术方法。本文聚焦工程落地——从环境陷阱规避、同步/异步协同设计,到 numpy 零拷贝实践与 wheel 分

weixin_33802505的博客 259

Python爬虫实战:爬取ETF基金持仓变化

在python复制编辑本文详细介绍了如何使用Python的Scrapy框架爬取ETF基金的持仓变化信息,包括项目的搭建、数据的提取与存储、以及数据的可视化分析。通过本项目,读者可以掌握基本的网页爬虫技术,并应用于实际的财经数据采集与分析中。

2201_76125261的博客 629

Rust+Python混合架构实战:构建高并发服务的终极方案

auto-generated

FuncWander的博客 771

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

从Rust到Python:开源项目第一个PR实战指南

在开源社区中,跨语言协作日益普遍,Rust与Python的组合凭借高性能核心与灵活接口成为热门架构。本文从基础概念出发,解析Rust与Python混合项目的设计原理,探讨如何通过绑定层实现高效通信。通过参与这类项目,开发者不仅能提升编码能力,还能掌握GitHub协作流程。对于想提交第一个PR的新手,选择合适的开源项目、配置环境、理解代码结构是成功关键。文章结合实战经验,分享了从Rust模块改造到Python调用层对接的完整过程,并提供了常见问题避坑指南。无论你是Rust爱好者还是Python开发者,都能从中

weixin_34174105的博客 268

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Rust与Mojo如何重构AI基础设施:性能、安全与Python生态的融合

在AI与高性能计算领域,编程语言的选择直接影响着系统的性能、安全性与开发效率。传统上,Python凭借其简洁语法和丰富生态成为算法开发的首选,但在处理计算密集型任务、并发编程和内存管理时,其解释执行、全局解释器锁(GIL)等机制常成为性能瓶颈。为解决这一问题,系统级编程语言Rust和新兴语言Mojo提供了不同的技术路径。Rust通过所有权模型和零成本抽象,在编译期保障内存安全与线程安全,成为构建高性能、可靠底层组件(如服务器、数据管道)的理想选择。Mojo则作为Python的超集,在保持语法兼容性的同时,引

weixin_33860553的博客 540

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

上一篇: Rust多线程传递给Python是否会被GIL
下一篇: Pyo3学习2
String vs Array
博客等级 码龄6年 11粉丝 52原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值