如何在 Rust 中迭代 pyo3 PyObject?

发布于 2025-01-09 06:22:24 字数 1465 浏览 6 评论 0 原文

我有一个预导入的模块,我正在使用 python gil 调用一个方法,如下所示。

Python::with_gil(|py| {
    let res = module.call_method1(py, "my_method", (arg1, arg2))?;
})

这会返回 rust 对象 PyObject,但是返回的是一个 python list。我想迭代这个列表,将内部转换为我可以在 Rust 中使用的东西(它是 Numpy 数组的 python 列表,我正在使用 numpy/ndarray 板条箱)。

我对如何迭代这个有点困惑。如果我尝试将 cast_as 转换为 PyList,我会收到警告:UnsafeCell无法在线程之间安全地共享。看来extract也不起作用。

如何迭代这个 PyObject?谢谢。

编辑:根据要求添加更多详细信息

如果您使用的是 python 打字系统,则 python 返回的值是一个 List[numpy.ndarray]。由于每个 numpy 数组的长度可能不同,我不能将其全部转换为 python 中的 numpy 数组并传递它。示例输出如下:

[array([214.17725372, 192.78236675, 354.27965546, 389.84558392,
          0.99999297])]

我在 Rust 中尝试过的内容:

  • let pylist = res.cast_as::(py)?;

    无法编译:UnsafeCell;无法在线程之间安全地共享

  • let pylist = res.extract::(py)?;

    无法编译:未针对“PyList”实现特征“PyClass”。请注意,我在顶部有use pyo3::prelude::*;

  • let pyany = res.extract::>>(py)?;

    无法编译:特征绑定 'Vec>: pyo3::FromPyObject<'_>'不满意。这个 PyArray 来自 numpy 板条箱。

I have a pre-imported module that I'm calling a method with python gil, something like the following.

Python::with_gil(|py| {
    let res = module.call_method1(py, "my_method", (arg1, arg2))?;
})

This returns the rust object PyObject, however what this returns is a python list. I want to iterate over this list to convert the internals into something I can use in Rust (it's a python list of Numpy arrays, I'm using the numpy/ndarray crates).

I'm a little confused as to how I'm meant to iterate over this. If I try cast_as to a PyList, I get the warning: UnsafeCell<PyObject> cannot be shared between threads safely. It seems extract does not work either.

How do I iterate over this PyObject? Thanks.

Edit: Adding further details as requested

The returned value from python is a List[numpy.ndarray] if you are using the python Typing system. As the lengths of each numpy array could be different, I cannot just convert it all into a numpy array in python and pass it through. An example output is below:

[array([214.17725372, 192.78236675, 354.27965546, 389.84558392,
          0.99999297])]

What I've tried in Rust:

  • let pylist = res.cast_as::<PyList>(py)?;

    Fails to compile with: UnsafeCell<PyObject> cannot be shared between threads safely.

  • let pylist = res.extract::<PyList>(py)?;

    Fails to compile with: the trait 'PyClass' is not implemented for 'PyList'. Please note I have use pyo3::prelude::*; at the top.

  • let pyany = res.extract::<Vec<PyArray1<f64>>>(py)?;

    Fails to compile with: the trait bound 'Vec<PyArray<f64, Dim<[usize; 1]>>>: pyo3::FromPyObject<'_>' is not satisfied. This PyArray is from the numpy crate.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不及他 2025-01-16 06:22:24

我看到您返回了带有 dtype=floatnumpy 数组列表。如果您愿意使用其他依赖项,可以使用 rust-numpy 来映射 numpy 数组到 ndarrays

ndarrays 有一个 .to_vec() 方法来转换为标准 Rust 容器。

在您的情况下,您可以执行以下操作(未经测试):

use numpy::PyArray1;
use pyo3::{types::IntoPyDict, PyResult, Python};

Python::with_gil(|py| {
    let res: Vec<&PyArray1<f32>> = module // <-- Notice the return type
                                 .call_method1(py, "my_method", (arg1, arg2))?
                                 .extract()?; // <--  Notice the extract
})

可以找到 Python 和 Rust 类型之间的映射

println!("I just got a numpy array from python {:?}", res[0]);
println!("I converted that to a vector here: {:?}", res[0].to_vec());

I see that you returning a list of numpy arrays with dtype=float. If you are open to using another dependency, there is rust-numpy which lets you map numpy arrays to ndarrays in Rust.

ndarrays have a .to_vec() method to convert to standard Rust containers.

In your case you could do the following (this is not tested):

use numpy::PyArray1;
use pyo3::{types::IntoPyDict, PyResult, Python};

Python::with_gil(|py| {
    let res: Vec<&PyArray1<f32>> = module // <-- Notice the return type
                                 .call_method1(py, "my_method", (arg1, arg2))?
                                 .extract()?; // <--  Notice the extract
})

Mappings between Python and Rust types can be found here. You can then use the res to do further computations.

println!("I just got a numpy array from python {:?}", res[0]);
println!("I converted that to a vector here: {:?}", res[0].to_vec());
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文