英文:
pyO3 and Panics
问题
我已经为您翻译好了所需的内容:
我已经使用pyO3将一些Python代码重写成了Rust。我遇到了这样一种情况:我的Rust代码可能会在我使用的第三方Rust库中的某个地方发生panic。对我来说,最简单的方法是在Python中捕获那个panic,然后退回到速度较慢但更可靠的Python方法。失败的情况很少,以至于退回到Python仍然比仅使用Python更有效率。有没有办法处理Rust的panic呢?从我所了解的情况来看,答案可能是“不行”,但我还是希望能有办法!
下面是我所说的内容的简化示例。非常感谢任何帮助!
(我知道我可以追踪每次panic的具体原因,但我认为这个问题仍然有一定价值。)
**lib.rs**
```rust
use numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};
use pyo3::{pymodule, types::PyModule, PyResult, Python};
#[pymodule]
fn can_panic(_py: Python, m: &PyModule) -> PyResult<()> {
#[pyfn(m)]
fn can_panic<'py>(
py: Python<'py>,
arr: PyReadonlyArray1<i64>,
) -> &'py PyArray1<bool> {
let my_arr = arr.as_array();
for v in my_arr {
if v == &-1 {
panic!("Hey, you can't do that!");
}
}
vec![true; my_arr.len()].into_pyarray(py)
}
Ok(())
}
Cargo.toml
[package]
name = "can_panic"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "can_panic"
crate-type = ["cdylib"]
[dependencies]
pyo3 = { version = "0.18.3", features = ["extension-module", "anyhow"] }
numpy = "0.18.0"
nalgebra = "0.32.2"
testing.py
import numpy as np
import can_panic
print("Staring filtering")
print(can_panic.can_panic(np.array([1, 2, 3], dtype="int64")))
print("Done filtering")
print("Staring Filtering")
try:
print(can_panic.can_panic(np.array([-1, 2, 3], dtype="int64")))
except Exception:
print("didn't work")
# call Python equivalent
print("Done filtering")
output
Staring filtering
[ True True True]
Done filtering
Staring Filtering
thread '<unnamed>' panicked at 'Hey, you can't do that!', src/lib.rs:16:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Traceback (most recent call last):
File "(snip...)/can_panic/testing.py", line 13, in <module>
print(can_panic.can_panic(np.array([-1, 2, 3], dtype="int64")))
pyo3_runtime.PanicException: Hey, you can't do that!
请注意,这只是您提供的代码的翻译版本,没有额外的内容。如果您需要进一步的帮助,请随时提问。
英文:
I have re-written some Python into Rust using pyO3. I have a situation where my Rust code can panic somewhere in a third party Rust library I use. The simplest thing for me would be to catch that panic in Python-land and fall back to the slower (but more resilient) Python method. The failure is rare enough that falling back to Python is still more efficient than only-Python. Is there any way to deal with the Rust panic? From what I've read the answer is probably "no," but I'm hoping!
Below is simplified example of what I mean. Any help is appreciated!
(I know I could/can track down the specific reason for each panic, but I think this question has merit anyway.)
lib.rs
use numpy::{IntoPyArray, PyArray1, PyReadonlyArray1};
use pyo3::{pymodule, types::PyModule, PyResult, Python};
#[pymodule]
fn can_panic(_py: Python, m: &PyModule) -> PyResult<()> {
#[pyfn(m)]
fn can_panic<'py>(
py: Python<'py>,
arr: PyReadonlyArray1<i64>,
) -> &'py PyArray1<bool> {
let my_arr = arr.as_array();
for v in my_arr {
if v == &-1 {
panic!("Hey, you can't do that!");
}
}
vec![true; my_arr.len()].into_pyarray(py)
}
Ok(())
}
Cargo.toml
[package]
name = "can_panic"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
name = "can_panic"
crate-type = ["cdylib"]
[dependencies]
pyo3 = { version = "0.18.3", features = ["extension-module", "anyhow"] }
numpy = "0.18.0"
nalgebra = "0.32.2"
testing.py
import numpy as np
import can_panic
print("Staring filtering")
print(can_panic.can_panic(np.array([1, 2, 3], dtype="int64")))
print("Done filtering")
print("Staring Filtering")
try:
print(can_panic.can_panic(np.array([-1, 2, 3], dtype="int64")))
except Exception:
print("didn't work")
# call Python equivalent
print("Done filtering")
output
Staring filtering
[ True True True]
Done filtering
Staring Filtering
thread '<unnamed>' panicked at 'Hey, you can't do that!', src/lib.rs:16:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Traceback (most recent call last):
File "(snip...)/can_panic/testing.py", line 13, in <module>
print(can_panic.can_panic(np.array([-1, 2, 3], dtype="int64")))
pyo3_runtime.PanicException: Hey, you can't do that!
答案1
得分: 1
Your except
doesn't work because as pyo3 documents PanicException
derives from BaseException
(like SystemExit
or KeyboardError
) as it's not necessarily safe (given not all rust code is panic safe, pyo3 does not assume a rust-level panic is innocuous).
Your options then would be, in decreasing order of desirability (as far as I'm concerned):
- improve the third-party library or your call to it so it does not panic
- use
catch_unwind
on the Rust side, and convert the panic to a more classic Error - catch the PanicException specifically, which is not great (and possibly not easy) as you probably don't want to catch BaseException
英文:
Your except
doesn't work because as pyo3 documents PanicException
derives from BaseException
(like SystemExit
or KeyboardError
) as it's not necessarily safe (given not all rust code is panic safe, pyo3 does not assume a rust-level panic is innocuous).
Your options then would be, in decreasing order of desirability (as far as I'm concerned):
- improve the third-party library or your call to it so it does not panic
- use
catch_unwind
on the Rust side, and convert the panic to a more classic Error - catch the PanicException specifically, which is not great (and possibly not easy) as you probably dont' want to catch BaseException
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论