英文:
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_unwindon 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_unwindon 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论