照例先创建初始话选pyo3
maturin init
修改src/lib.rs
rust
use pyo3::prelude::*;
use pyo3::types::{PyDict, PyTuple};
use pyo3::exceptions::PyValueError;
use pyo3::exceptions::PyOSError;
use std::num::ParseIntError;
use std::fmt;
// 定义一个类
#[pyclass]
struct MyClass {
num: i32,
}
// 实现类方法
#[pymethods]
impl MyClass {
#[new]
#[pyo3(signature = (num=-1))]
fn new(num:i32) -> Self {
MyClass { num }
}
#[pyo3(signature = (num=10,*py_args,name="Hello",**py_kwargs))]
fn method(
&mut self,
num: i32,
py_args: &Bound<'_, PyTuple>,// 接受任意个python位置参数(positional argument)
name: &str,
py_kwargs: Option<&Bound<'_, PyDict>>,// 接受任意个python关键字参数(keyword argument)
) -> String {
let num_before = self.num;
self.num = num;
format!(
"num={} (was previously={}), py_args={:?}, name={}, py_kwargs={:?} ",
num, num_before, py_args, name, py_kwargs,
)
}
fn make_change(&mut self, num: i32) -> PyResult<String> {
self.num = num;
Ok(format!("num={}", self.num))
}
}
#[pyfunction]
// 用new_err创建一个PyErr
fn check_positive(x: i32) -> PyResult<()> {
if x < 0 {
Err(PyValueError::new_err("x is negative"))
} else {
Ok(())
}
}
#[pyfunction]
fn parse_int(x: &str) -> Result<usize, ParseIntError> {
x.parse()
}
#[pyfunction]
fn parse_int2(x: &str) -> PyResult<usize> {
let x = x.parse()?;
Ok(x)
}
// 自定义IO错误CustomIOError
// 实现标准库的Error trait
// 实现Display trait
// 实现From trait,定义如何将自定义CustomIOError转换成PyO3的PyErr
#[derive(Debug)]
struct CustomIOError;
impl std::error::Error for CustomIOError {}
impl fmt::Display for CustomIOError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Oh no!")
}
}
impl std::convert::From<CustomIOError> for PyErr {
fn from(err: CustomIOError) -> PyErr {
PyOSError::new_err(err.to_string())
}
}
#[pyfunction]
fn parse_int3(x: &str) -> Result<usize,CustomIOError> {
match x.parse() {
Ok(parsed) => Ok(parsed),
Err(_) => Err(CustomIOError),
}
}
/// A Python module implemented in Rust.
#[pymodule]
mod my_extension_sign_err {
use pyo3::prelude::*;
use pyo3::types::{PyDict, PyTuple}; //python的字典格
#[pymodule_export]
use super::MyClass;
#[pymodule_export]
use super::check_positive;
#[pymodule_export]
use super::parse_int;
#[pymodule_export]
use super::parse_int2;
#[pymodule_export]
use super::parse_int3;
#[pyfunction]
#[pyo3(signature = (**kwds))]//接受任意个数参数
fn num_kwds(kwds: Option<&Bound<'_, PyDict>>) -> usize {
kwds.map_or(0, |dict| dict.len())
}
}
这段代码定义了一个名为 my_extension_sign_err 的 Python 模块,它包含一个类 MyClass 和多个函数(如 check_positive 和 parse_int)。代码展示了 PyO3 的核心功能:
- 使用
#[pyclass]和#[pymethods]定义 Python 类。 - 通过
#[pyfunction]导出 Python 函数。 - 处理错误和异常,包括自定义错误转换。
- 支持复杂的函数签名(如位置参数和关键字参数)。
先编译安装一下
rust
maturin develop
再写个脚本测试一下
python
import my_extension_sign_err
# 传入多个任意参数
print(my_extension_sign_err.num_kwds(a=1, b=2, c=3,d='ood'))
# 使用类方法
myclass = my_extension_sign_err.MyClass()
print(myclass.method(1,[2,3],'ood',a=1,b=2,c=3))
print(myclass.make_change(13))
print(myclass.method(1,[2,3],'ood',a=1,b=2,c=3))
# 使用异常处理,自定义PyErr
try:
res = my_extension_sign_err.check_positive(12)
print(res)
res = my_extension_sign_err.check_positive(-12)
print(res)
except Exception as e:
print(e)
# 使用异常处理,ParseIntError
try:
res = my_extension_sign_err.parse_int("11")
print(res)
res = my_extension_sign_err.parse_int("bar1")
print(res)
except Exception as e:
print(e)
# 使用异常处理,PyResult包装
try:
res = my_extension_sign_err.parse_int2("12")
print(res)
res = my_extension_sign_err.parse_int2("bar2")
print(res)
except Exception as e:
print(e)
# 使用异常处理,使用自定义CustomIOError
try:
res = my_extension_sign_err.parse_int3("13")
print(res)
res = my_extension_sign_err.parse_int3("bar3")
print(res)
except Exception as e:
print(e)
执行结果
