You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust+PyO3构建Python测试框架:如何处理任意数据库记录

在Rust中实现动态属性访问(适配PyO3场景)

当然可以实现,完全不用为每个数据库表定义固定的Rust结构体,利用PyO3提供的Python对象交互能力,就能达到和你Python动态属性类一样的效果。

方法1:直接用PyAny动态访问属性

PyO3中的PyAny类型可以代表任意Python对象,你可以直接用它来获取动态属性或者字典键值。比如你Python端的Result类实例传到Rust后,就可以用&PyAny接收,再通过getattr方法提取属性值。

示例代码:

use pyo3::prelude::*;

#[pyfunction]
fn test_amount_not_null(a: &PyAny) -> PyResult<bool> {
    // 提取amount属性为f64类型,可根据实际数据类型调整
    let amount: f64 = a.getattr("amount")?.extract()?;
    Ok(amount > 0.0)
}

#[pymodule]
fn underling(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(test_amount_not_null, m)?)?;
    Ok(())
}

如果你的数据库查询结果直接是Python字典(而非自定义Result类),把getattr换成get_item即可:

let amount: f64 = a.get_item("amount")?.extract()?;

方法2:封装轻量结构体优化代码可读性(可选)

如果想让代码更规整,可以封装一个简单结构体包裹PyAny,提供统一的属性提取方法:

use pyo3::prelude::*;

struct DynamicRecord<'a>(&'a PyAny);

impl<'a> DynamicRecord<'a> {
    fn new(obj: &'a PyAny) -> Self {
        DynamicRecord(obj)
    }

    // 通用属性提取方法,支持任意可转换的Rust类型
    fn get<T: FromPyObject<'a>>(&self, name: &str) -> PyResult<T> {
        self.0.getattr(name)?.extract()
    }
}

#[pyfunction]
fn test_amount_not_null(a: &PyAny) -> PyResult<bool> {
    let record = DynamicRecord::new(a);
    let amount: f64 = record.get("amount")?;
    Ok(amount > 0.0)
}

#[pymodule]
fn underling(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(test_amount_not_null, m)?)?;
    Ok(())
}

关键注意点

  • 类型匹配:提取属性时要确保Rust类型和Python端的数据类型兼容,比如数据库返回的整数可以用i64接收,浮点数用f64,字符串用String。
  • 错误处理:getattr/get_item和extract都会返回PyResult,这些错误会自动转为Python异常抛出,无需额外处理就能让Python端捕获到问题(比如属性不存在、类型不匹配)。

内容的提问来源于stack exchange,提问作者seve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 11:30:50