我在之前的博客中分享了使用Python调用C语言动态链接库的相关内容,在开发中我们也可以很方便地使用maturin配合pyo3为Python开发可调用的Rust模块来加速Python程序,这篇博客就来分享一下入门的用法

环境配置

maturin安装

关于Rust环境的配置这里就不多介绍了,具体可以参考之前的博客,这里介绍一下maturin的安装,具体命令如下

1
pip install maturin

环境初始化

maturin安装完成后,可以使用以下的命令进行Rust环境的初始化

1
2
# 初始化编译环境命令
maturin new sum

运行完成后可以看见当前目录下新增了sum目录,这就是我们的项目目录

实例:编写Rust下的累加函数

编辑lib.rs文件

1
2
cd sum
vi src/lib.rs

Rust代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use pyo3::prelude::*;

#[pyfunction]
fn add_up_u128(x: u128) -> PyResult<u128> {
let mut sum = 0;
let mut i = 0;

while i <= x {
sum += i;
i += 1;
}
Ok(sum)
}

#[pymodule]
fn sum(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(add_up_u128, m)?)?;
Ok(())
}

编译、安装模块

使用maturin时有两种方式安装Python模块

直接编译、安装

模块代码编写完成之后,直接在项目目录下运行

1
2
3
4
# 编译项目
maturin build --release
# 安装模块(注意:此处需根据具体whl文件名称确定安装文件)
pip install target/wheels/sum-0.1.0-cp39-cp39-manylinux_2_34_x86_64.whl

注意:修改Rust模块代码导致需要重新安装模块时,可能需要添加--force-reinstall参数

使用Python虚拟环境安装

1
2
3
4
5
6
# 创建Python虚拟环境
python -m venv virtualenv
# 运行虚拟环境
source virtualenv/bin/activate
# 安装模块(项目目录运行)
maturin develop --release

注意:使用这种方法安装模块,之后想调用该模块时都需要先运行已安装模块的虚拟环境

Python代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import time
import sum

def num_add_up(x: int) -> None:
start = time.time()
result: int = sum.add_up_u128(x)
print(result)
print(time.time()-start)

if __name__ == "__main__":
num_add_up(100000000)

输出:
5000000050000000
0.08351874351501465

数据类型映射关系

和ctypes类似,使用Rust模块时也需要进行数据类型的映射,以下是一些Rust和Python的基础数据类型对应关系

Rust 类型 Python 类型
i32 int
i64 int
i128 int
f32 float
f64 float
bool bool
string str
Vec<T> list
[T; N] list
(T1, T2, …) tuple
HashMap<K, V> dict

除以上数据类型外,还有其他如struct类型Result类型Option类型等,这些就不一一列出了

小结

其实从上面的运行结果可以看出,使用Rust编写的模块在速度上较C语言稍慢,但Rust在内存安全和数据类型支持上比C语言更好,比如读者可以将累加的数据设置为10000000000再运行一下查看结果。同时,也可以看出Rust模块在编写和调用时也更加简单