I'm attempting to open and write to a database in a Rust library I will call from python, with the help of pyo3. If an error occurs, I would like to raise an exception that can be caught in the calling Python process, but I'm having difficulties terminating execution and raising an error.
use rusqlite::{Connection};
use rusqlite::NO_PARAMS;
use pyo3::{Python, wrap_pyfunction};
use pyo3::exceptions::PyIOError;
#[pyfunction]
fn do_something(_py: Python) -> PyResult<u32> {
match Connection::open("database.sql") {
Ok(t) => conn = t,
Err(e) => {
let gil = Python::acquire_gil();
let py = gil.python();
let error_message = format!("Unable to open database! {}", e.to_string());
PyIOError::new_err(error_message).restore(py)
}
};
match conn.execute(
"create table if not exists cats (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
)",
NO_PARAMS,
) {
Ok(_t) => (),
Err(e) => {
let gil = Python::acquire_gil();
let py = gil.python();
let error_message = format!("Unable to open database! {}", e.to_string());
PyIOError::new_err(error_message).restore(py)
}
}
Ok(0)
It's my understanding that by calling the restore
function on the PyIOError
object, an error would be raised, however, I must be misunderstanding because the compiler seems to consider it a possibility that conn
is not initialised:
error[E0381]: borrow of possibly-uninitialized variable: `conn`
18 | match conn.execute(
| ^^^^ use of possibly-uninitialized `conn`
What would be an appropriate approach here?
First of all, your
Ok(t) = conn = t
fails, as you haven't definedconn
. So prior to thematch
addlet conn;
. Alternatively, you can also just assign the result of the match toconn
.Second, you still need to return an
Err
.It's been some time since I used PyO3. But unless I remember incorrectly, then you can just remove
restore()
also just return theErr
and let PyO3 handle the rest.