So, I've written a "Cython" tutorial for calling C ++ libraries from Python to speed things up.
From this time, I will write a tutorial of a library called "PyO3" to call Rust from Python and speed it up.
The ultimate goal is
Being able to easily call functions and classes (like things?) Written in rust from python
is.
This PyO3 (git is here) is in the middle of development and version updates are (probably) at a tremendous rate.
In the first place, starting from the state of Rust's first look, I touched PyO3 with the goal of being able to call functions written in Rust from Python.
There are some commentary articles on Kita and other blogs. -[Rust] Create Python package with PyO3 -Link Python and Rust with Pyo3 -Run Rust module from Python (PyO3) -Write a Python extension module using Python and Rust
This time, Run Rust module from Python (PyO3) I'd like to borrow your code, add setup.py to it, and call a function written in Rust from Python.
Install rust
When you execute the first line, you will be asked about the installation with 3 choices, but I think that there is no problem selecting 1 of the default installation.
curl https://sh.rustup.rs -sSf | sh
source $HOME/.cargo/env
Install rust nightly
You will need it to use PyO3. Is it something like a beta version that contains a lot of crates under development?
Check the version I will use this version this time.
$rustc --version
rustc 1.44.0-nightly (f509b26a7 2020-03-18)
$ rustup --version
rustup 1.21.1 (7832b2ebe 2019-12-20)
rustup install nightly
rustup default nightly
Create a rust project
Create a project for the library by adding --lib
.
This time, the project name is ʻexample`.
cargo new --lib example
$ tree example/
├── Cargo.toml
├── setup.py
├── src
│ └── lib.rs
The folder structure looks like this.
One of the things that Rust is said to be better than C ++ is the ease of managing libraries.
I write the necessary libraries in Cargo.toml
, but it's much easier and easier to read than CMakeLists.txt
.
Cargo.toml
[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"]
This time I used pyo3 as a library and
The target library to create is test_library
.
That is, in Python
test.py
import test_library
I want to write like this.
Try copying sutras for the time being
The code is Run Rust module from Python (PyO3) I brought all of his stuff. It's an implementation of the Eratosthenes sieve.
//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)
}
I don't have the ability to explain Rust's syntax in detail, so Let's assume that this function is correct, and explain how it is wrapped in a form that can be called from Python.
#[pyfunction]
fn get_prime_numbers(n: i32) -> PyResult<Vec<i32>>
If you look at First, the decorator of `` `# [pyfunction] ``` declares that the argument or return value of this function will contain a Python object parsed by PyO3.
This get_prime_numbers
function takes int32 as an argument and returns a list of prime numbers less than that.
At this time, the return value is `PyResult <Vec <i32 >>`
,
This PyResult
comes from ```use pyo3 :: prelude :: *;` ``.
Also, `Vec <i32>`
is as shown in the type correspondence table below, and is converted to Python List type by PyResut.
Rust | Python |
---|---|
i32 , usize etc |
int |
f32 , f64 |
float |
bool |
bool |
Vec<T> |
list |
String |
str |
HashMap |
dict |
Quoted from [Rust] Create Python package with PyO3
Also the last
Ok(primes)
Is converting `Vec``` to
`list```.
I'm sorry that if you end here, you'll end up with a copy of most of the references. I will separate it here once.
In summary,
--I installed Rust. --Created a project for Rust's library. --Written Cargo.toml. --I copied the function and confirmed the type conversion of Rust-> Python.
That's it.
Next, add lib.rs
, add setup.py
, and actually compile it as an object file of the library.
This time around here.
end.
Recommended Posts