创建一个rust写的python库[signatures和错误处理]

照例先创建初始话选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_positiveparse_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)

执行结果

相关推荐
Source.Liu3 小时前
【time-rs】解释://! Invalid format description(error/invalid_format_description.rs)
rust·time
hahjee3 小时前
Go编写的ANSI终端颜色和样式控制库在OpenHarmony PC上的完整适配实战
开发语言·后端·鸿蒙
拉姆哥的小屋3 小时前
从400维向量到160000维矩阵:基于深度学习的火焰参数预测系统全解析
开发语言·人工智能·python·深度学习·线性代数·算法·矩阵
雨落在了我的手上3 小时前
C语言入门(二十八):动态内存管理(2)
c语言·开发语言
矢鱼3 小时前
python中对应c++容器的结构
开发语言·c++·python·算法
Source.Liu3 小时前
【time-rs】解释://! Indeterminate offset(error/indeterminate_offset.rs)
rust·time
Doris8933 小时前
【JS】JS进阶--编程思想、面向对象构造函数、原型、深浅拷贝、异常处理、this处理、防抖节流
开发语言·javascript·ecmascript
古城小栈3 小时前
Java 内存优化:JDK 22 ZGC 垃圾收集器调优
java·python·算法
Clarence Liu3 小时前
golang 剖析 sync包
开发语言·golang