提问人:Nils Werner 提问时间:10/14/2023 更新时间:11/4/2023 访问量:44
PyO3 将 TryFrom 错误转换为 PyErr
PyO3 turn TryFrom errors into PyErr
问:
我正在尝试为一些 Rust 代码编写一个 Python 包装器,它在内部进行一些转换:TryFrom
pub enum MicrophoneType {
Bidirectional,
Omnidirectional,
}
impl TryFrom<char> for MicrophoneType {
type Error = &'static str;
fn try_from(x: char) -> Result<Self, Self::Error> {
match x {
'b' => Ok(Self::Bidirectional),
'o' => Ok(Self::Omnidirectional),
_ => Err("MicrophoneType: Invalid character given"),
}
}
}
#[pyfunction]
fn compute(
_py: Python,
microphone: char,
) -> PyResult<()> {
let _microphone = MicrophoneType::try_from(microphone)?;
Ok(())
}
但是,我看到错误消息
error[E0277]: `?` couldn't convert the error to `PyErr`
--> rir_generator_py/src/lib.rs:59:59
|
58 | ) -> PyResult<()> {
| ------------ expected `PyErr` because of this
59 | let _microphone = MicrophoneType::try_from(microphone)?;
| ^ the trait `From<&str>` is not implemented for `PyErr`
我对为什么感到困惑。
看来PyO3不知道如何处理我的类型,对吧?但这难道不是给出错误消息的默认方式吗?如果 PyO3 是一种常见模式,难道不应该期待这些吗?我在这里错过了什么?type Error = &'static str;
impl
答:
1赞
Nils Werner
10/15/2023
#1
找到这些文档后,我意识到了一些事情:
首先,这不是一个好的模式,相反,如果需要,您应该使用可以 ed 和 /ed 的自定义错误type Error = &'static str;
match
From
Into
#[derive(Debug)]
pub struct InvalidMicrophoneCharError {}
impl Error for InvalidMicrophoneCharError {}
impl fmt::Display for InvalidMicrophoneCharError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Incorrect microphone character")
}
}
impl TryFrom<char> for MicrophoneType {
type Error = InvalidMicrophoneCharError;
fn try_from(x: char) -> Result<Self, Self::Error> {
match x {
'b' => Ok(Self::Bidirectional),
'o' => Ok(Self::Omnidirectional),
_ => Err(InvalidMicrophoneCharError {}),
}
}
}
其次,你必须使用 newtype 模式创建一个 “-chain”,它以 your type 开头,以 a 结尾,然后可以与 PyO3 对 Rust 原生 s 的支持相结合:From
PyErr
Result<T, E>
struct MyInvalidMicrophoneCharError(InvalidMicrophoneCharError);
impl From<MyInvalidMicrophoneCharError> for PyErr {
fn from(err: MyInvalidMicrophoneCharError) -> Self {
PyValueError::new_err(err.0.to_string())
}
}
impl From<InvalidMicrophoneCharError> for MyInvalidMicrophoneCharError {
fn from(other: InvalidMicrophoneCharError) -> Self {
Self(other)
}
}
#[pyfunction]
fn compute(
_py: Python,
microphone: char,
) -> Result<(), MyInvalidMicrophoneCharError> {
let _microphone = MicrophoneType::try_from(microphone)?;
Ok(())
}
或者跳过链条,直接使用map_err()
#[pyfunction]
fn compute(
_py: Python,
microphone: char,
) -> Result<(), MyInvalidMicrophoneCharError> {
let _microphone = MicrophoneType::try_from(microphone)
.map_err(|error| PyValueError::new_err(error.to_string()))?;
Ok(())
}
评论