rusqlite 和 pyo3 PyResult 处理错误
rusqlite and pyo3 PyResult handling errors
我正在尝试在 pyo3 的帮助下打开并写入我将从 python 调用的 Rust 库中的数据库。如果发生错误,我想引发一个可以在调用 Python 进程中捕获的异常,但我在终止执行和引发错误时遇到困难。
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)
据我了解,通过在 PyIOError
对象上调用 restore
函数,会引发错误,但是,我一定是误会了,因为编译器似乎认为有可能 conn
未初始化:
error[E0381]: borrow of possibly-uninitialized variable: `conn`
18 | match conn.execute(
| ^^^^ use of possibly-uninitialized `conn`
这里什么是合适的方法?
首先,你的 Ok(t) = conn = t
失败了,因为你还没有定义 conn
。所以在 match
之前添加 let conn;
。或者,您也可以将匹配结果分配给 conn
.
其次,你还需要return一个Err
。
#[pyfunction]
fn do_something(_py: Python) -> PyResult<u32> {
let conn = match Connection::open("database.sql") {
Ok(t) => 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);
return Err(PyErr::fetch(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);
return Err(PyErr::fetch(py));
}
}
Ok(0)
}
我已经有一段时间没有使用 PyO3 了。但是除非我记错了,否则你可以只删除 restore()
也只是 return 和 Err
并让 PyO3 处理其余的。
#[pyfunction]
fn do_something(_py: Python) -> PyResult<u32> {
let conn = match Connection::open("database.sql") {
Ok(t) => t,
Err(e) => {
let error_message = format!("Unable to open database! {}", e.to_string());
return Err(PyIOError::new_err(error_message));
}
};
match conn.execute(
"create table if not exists cats (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
)",
NO_PARAMS,
) {
Ok(_t) => (),
Err(e) => {
let error_message = format!("Unable to open database! {}", e.to_string());
return Err(PyIOError::new_err(error_message));
}
}
Ok(0)
}
我正在尝试在 pyo3 的帮助下打开并写入我将从 python 调用的 Rust 库中的数据库。如果发生错误,我想引发一个可以在调用 Python 进程中捕获的异常,但我在终止执行和引发错误时遇到困难。
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)
据我了解,通过在 PyIOError
对象上调用 restore
函数,会引发错误,但是,我一定是误会了,因为编译器似乎认为有可能 conn
未初始化:
error[E0381]: borrow of possibly-uninitialized variable: `conn`
18 | match conn.execute(
| ^^^^ use of possibly-uninitialized `conn`
这里什么是合适的方法?
首先,你的 Ok(t) = conn = t
失败了,因为你还没有定义 conn
。所以在 match
之前添加 let conn;
。或者,您也可以将匹配结果分配给 conn
.
其次,你还需要return一个Err
。
#[pyfunction]
fn do_something(_py: Python) -> PyResult<u32> {
let conn = match Connection::open("database.sql") {
Ok(t) => 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);
return Err(PyErr::fetch(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);
return Err(PyErr::fetch(py));
}
}
Ok(0)
}
我已经有一段时间没有使用 PyO3 了。但是除非我记错了,否则你可以只删除 restore()
也只是 return 和 Err
并让 PyO3 处理其余的。
#[pyfunction]
fn do_something(_py: Python) -> PyResult<u32> {
let conn = match Connection::open("database.sql") {
Ok(t) => t,
Err(e) => {
let error_message = format!("Unable to open database! {}", e.to_string());
return Err(PyIOError::new_err(error_message));
}
};
match conn.execute(
"create table if not exists cats (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
)",
NO_PARAMS,
) {
Ok(_t) => (),
Err(e) => {
let error_message = format!("Unable to open database! {}", e.to_string());
return Err(PyIOError::new_err(error_message));
}
}
Ok(0)
}