从Python调用Rust可以加快速度! PyO3教程:包装一个简单的函数吗?


概述

1.就速度而言,用Pyhton编写算法不是更可取的吗?
2.好吧,寻找一些用C,C编写的东西,并从Python调用它以加快速度。
3.我找不到一个好的图书馆,
4.哦,如果它是用Rust语言编写的
5.可以从Python调用Rust吗? ??

最终目标

因此,我编写了一个" Cython"教程,用于从Python调用C库来加速它,但是

从这时起,我将编写一个名为" PyO3"的库的教程,以从Python调用Rust并加速它。

最终目标是
Rustで書いた関数やクラス(的なもの?)をPythonから気軽に呼べるようになること
是。

此PyO3(此处为git)正在开发中,版本更新(可能)的速度非常快。

这次目标

从Rust的初看起来状态开始,
我接触PyO3的目的是能够从Python调用用Rust编写的函数。

在Kita和其他博客上有一些评论文章。
-[Rust]使用PyO3创建Python包
-将Python和Rust与Pyo3集成
-从Python(PyO3)运行Rust模块
-使用Python和Rust

编写Python扩展模块

这次,
从Python(PyO3)运行Rust模块
我想借用您的代码,向其中添加setup.py,然后从Python调用用Rust编写的函数。

步骤

安装rust

在执行第一行时,系统会询问您3种选择的安装,但是我认为选择默认安装中的1种没有问题。

1
2
curl https://sh.rustup.rs -sSf | sh
source $HOME/.cargo/env

每晚安装防锈

需要使用PyO3。
它像是Beta版本,其中包含大量正在开发的包装箱吗?

检查版本
这次我将使用此版本。

1
2
3
4
$rustc --version
rustc 1.44.0-nightly (f509b26a7 2020-03-18)
$ rustup --version
rustup 1.21.1 (7832b2ebe 2019-12-20)
1
2
rustup install nightly
rustup default nightly

创建一个锈项目

通过添加

--lib为该库创建一个项目。
这次,项目名称为example

1
2
3
4
5
6
7
cargo new --lib example

$ tree example/
├── Cargo.toml
├── setup.py
├── src
│   └── lib.rs

文件夹结构如下所示。

设置Cargo.toml

据说Rust比C更好的一件事是易于管理库。
我为Cargo.toml编写了必要的库,但是它比CMakeLists.txt更容易阅读。

货代

1
2
3
4
5
6
7
8
9
10
11
12
[package]
name = "test"
version = "0.1.0"
edition = "2018"

[lib]
name = "test_library"
crate-type = ["cdylib"]

[dependencies.pyo3]
version = "0.9.1"
features = ["extension-module"]

这次我使用pyo3作为库,
要创建的目标库是test_library

即Python中的

test.py

1
import test_library

我想像

这样写。

在Rust

中创建函数

暂时复制经文

代码从Python(PyO3)运行Rust模块。
我带走了他所有的东西。
这是Eratosthenes筛子的实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//lib.rs

use pyo3::prelude::*;


// This is the test function in Rust, getting prime number, which is called by python as get_prime_numbers
#[pyfunction]
fn get_prime_numbers(n: i32) -> PyResult<Vec<i32>> {
    let mut flags = Vec::new();
    for _ in 0..n+1 {
        flags.push(true);
    }

    let upper = (n as f32).sqrt().floor() as i32;
    for i in 2..upper+1 {
        if !flags[i as usize] {
            continue;
        }

        let prime = i;

        let mut j = prime * 2;
        while j <= n {
            flags[j as usize] = false;
            j += prime;
        }
    }

    let mut primes = Vec::new();
    for i in 2..n+1 {
        if flags[i as usize] {
            primes.push(i);
        }
    }

    Ok(primes)
}

我无法详细解释Rust的语法,所以
让我们假设该函数是正确的,并说明如何将其包装为可从Python调用的形式。

1
2
#[pyfunction]
fn get_prime_numbers(n: i32) -> PyResult<Vec<i32>>

看着


首先,#[pyfunction]装饰器声明此函数的参数或返回值将包含由PyO3解析的Python对象。

get_prime_numbers函数将int32作为参数,并返回一个小于此的素数列表。
此时,返回值为PyResult<Vec<i32>>,但
PyResult来自use pyo3::prelude::*;

另外,Vec<i32>看起来像下面的类型对应表,并由PyResut转换为Python List类型。

<表格>

Rust

Python


<身体>

i32usize

int

f32f64

float

bool

bool

Vec<T>

list

String

str

HashMap

dict


引自

[[Rust]使用PyO3创建Python包](https://qiita.com/osanshouo/items/671888bdd6afeec1e939)

另外,最后一个

1
Ok(primes)

正在将Vec转换为list

摘要

很抱歉,我在此处结束时几乎复制并粘贴了引用,但是
我将在这里分开一次。

总之,

  • 我安装了Rust。
  • 我为Rust库创建了一个项目。
  • 我写了Cargo.toml。
  • 复制功能,Rust-