问题描述
我想编写一个函数来读取文件的内容,如果失败则引发错误。我想从 python 脚本调用这个函数,所以我在下面提到了一些 Python,以防它可能相关。
正如我在评论中尝试显示的那样,更多的工作可能会引发其他类型的错误,所以如果可能的话,我想使用通用错误,如果这在 Rust(?) 中是可能的。我怎样才能返回错误,以便它可以被处理并包装在一个 python 错误中,如 do_work
所示?不确定我导致以下错误的方法是否正确。
fn work_with_text() -> Result<(),dyn std::error::Error> {
let content = match std::fs::read_to_string("text.txt") {
Ok(t) => t,Err(e) => return Err(e),};
// do something with content that may cause another type of error (rusqlite error)
Ok(())
}
#[pyfunction]
fn do_work(_py: Python) -> PyResult<u32> {
match work_with_text() {
Ok(_) => (0),Err(e) => {
let gil = Python::acquire_gil();
let py = gil.python();
let error_message = format!("Error happened {}",e.to_string());
PyIOError::new_err(error_message).restore(py);
return Err(PyErr::fetch(py));
}
};
// ...
}
错误:
1 | ... fn work_with_text() -> Result<(),dyn std::error::Error> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size kNown at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn std::error::Error + 'static)`
解决方法
您当前的版本不起作用,因为 trait 对象没有静态已知的大小,这意味着编译器不知道在堆栈上为它们分配多少空间,因此您不能使用 unsized 类型作为函数参数或返回值除非您通过将它们放在指针后面来调整它们的大小。
固定示例:
fn work_with_text() -> Result<(),Box<dyn std::error::Error>> {
let content = std::fs::read_to_string("text.txt")?;
// do something with content that may cause another type of error (rusqlite error)
Ok(())
}
拥有 Box<dyn std::error::Error>
还允许您从函数中返回各种错误,因为大多数错误类型都可以通过 Box<dyn std::error::Error>
运算符自动转换为 ?
。
如果您想更深入地了解 Rust 中的大小和错误处理,我强烈建议您阅读 Sizedness in Rust 和 Error Handling in Rust。