Search code examples
rustpyo3

Raising an exception with pyo3


How do I correctly raise an Exception?

I've tried the following:

#[pymethods]
impl Foo {
    #[new]
    fn __new__(arg1: u8, ...) -> Self {
        if arg1 > LIMIT {
            let gil = Python::acquire_gil();
            let py = gil.python();
            PyErr::new::<exceptions::ValueError, _>("Parameter arg1 has invalid value").restore(py);
        }
        Foo {...}
    }

This is exactly the same implementation as how it is described here.

When I create an instance of Foo with an invalid parameter value then instead of a ValueError a SystemError is raised with error text <class 'Foo'> returned a result with an error set.

I'm using pyo3 0.11.1 and Rust 1.47.0 nightly on Linux.


Solution

  • You can use a PyResult that returns an exception (which will be raised in python):

    #[pymethods]
    impl Foo {
        #[new]
        fn __new__(arg1: u8, ...) -> PyResult<Self> {
            if arg1 > LIMIT {
                Err(exceptions::PyValueError::new_err("Parameter arg1 has invalid value"))
            } else {
                Ok(Foo {...})
            }
        }