简体   繁体   English

如何使用 PyO3 从 Python 访问 Rust 迭代器?

[英]How can I access a Rust Iterator from Python using PyO3?

I'm quite new with Rust, and my first 'serious' project has involved writing a Python wrapper for a small Rust library using PyO3.我对 Rust 很陌生,我的第一个“严肃”项目涉及使用 PyO3 为小型 Rust 库编写 Python 包装器。 This has mostly been quite painless, but I'm struggling to work out how to expose lazy iterators over Rust Vec s to Python code.这基本上很轻松,但我正在努力研究如何将 Rust Vec上的惰性迭代器暴露给 Python 代码。

So far, I have been collecting the values produced by the iterator and returning a list, which obviously isn't the best solution.到目前为止,我一直在收集迭代器产生的值并返回一个列表,这显然不是最好的解决方案。 Here's some code which illustrates my problem:这是一些说明我的问题的代码:

use pyo3::prelude::*;

// The Rust Iterator, from the library I'm wrapping.
pub struct RustIterator<'a> {
    position: usize,
    view: &'a Vec<isize>
}

impl<'a> Iterator for RustIterator<'a> {
    type Item = &'a isize;

    fn next(&mut self) -> Option<Self::Item> {
        let result = self.view.get(self.position);
        if let Some(_) = result { self.position += 1 };
        result
    }
}

// The Rust struct, from the library I'm wrapping.
struct RustStruct {
    v: Vec<isize>
}

impl RustStruct {
    fn iter(&self) -> RustIterator {
        RustIterator{ position: 0, view: &self.v }
    }
}

// The Python wrapper class, which exposes the 
// functions of RustStruct in a Python-friendly way.
#[pyclass]
struct PyClass {
    rust_struct: RustStruct,
}

#[pymethods]
impl PyClass {
    #[new]
    fn new(v: Vec<isize>) -> Self {
        let rust_struct = RustStruct { v };
        Self{ rust_struct }
    }

    // This is what I'm doing so far, which works
    // but doesn't iterate lazily.
    fn iter(&self) -> Vec<isize> {
        let mut output_v = Vec::new();
        for item in self.rust_struct.iter() {
            output_v.push(*item);
        }
        output_v
    }
}

I've tried to wrap the RustIterator class with a Python wrapper, but I can't use PyO3's #[pyclass] proc.我试图用 Python 包装器包装RustIterator class,但我不能使用 PyO3 的#[pyclass] proc。 macro with lifetime parameters.带有生命周期参数的宏。 I looked into pyo3::types::PyIterator but this looks like a way to access a Python iterator from Rust rather than the other way around.我查看了pyo3::types::PyIterator但这看起来像是一种从 Rust 访问 Python 迭代器的方法,而不是相反。

How can I access a lazy iterator over RustStruct.v in Python?如何在RustStruct.v中通过 RustStruct.v 访问惰性迭代器? It's safe to assume that the type contained in the Vec always derives Copy and Clone , and answers which require some code on the Python end are okay (but less ideal).可以安全地假设Vec中包含的类型始终派生CopyClone ,并且需要 Python 端的一些代码的答案是可以的(但不太理想)。

You can make your RustIterator a pyclass and then implement the proper trait ( PyIterProtocol ) using the rust iter itself.您可以将RustIterator pyclass ,然后使用 rust 迭代器本身实现适当的特征( PyIterProtocol )。

Not tested, but something like:未经测试,但类似:

#[pyclass]
pub struct RustIterator<'a> {
    position: usize,
    view: &'a Vec<isize>
}

impl<'a> Iterator for RustIterator<'a> {
    type Item = &'a isize;

    fn next(&mut self) -> Option<Self::Item> {
        let result = self.view.get(self.position);
        if let Some(_) = result { self.position += 1 };
        result
    }
}

#[pyproto]
impl PyIterProtocol for Iter {
    fn __next__(mut slf: PyRefMut<Self>) -> IterNextOutput<usize, &'static str> {
        match self.next() {
            Some(value) => IterNextOutput::Yield(value),
            None => IterNextOutput::Return("Ended")
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用 pyo3 从 Python 文件调用 Rust 函数? - How to call a Rust function from a Python file using pyo3? 如何在创建Python class时使用Rust中的pyo3创建析构函数方法? - How can I create a destructor method using pyo3 in Rust when creating a Python class? 使用 PyO3 从 Python 将列表列表作为参数传递给 Rust - Pass list of lists as argument to Rust from Python using PyO3 如何使用 pyo3 将 Rust function 作为回调传递给 Python - How to pass a Rust function as a callback to Python using pyo3 如何在 PyO3 中实现 python 运算符 - How can I implement python operators in PyO3 您可以在 rust (pyo3) 中编写库的一部分,但在 python 中编写 rest 吗? - Can you write part of a library in rust (pyo3) but the rest in python? Python 的键盘中断不会中止 Rust function (PyO3) - Keyboard Interrupt from Python does not abort Rust function (PyO3) __str__ function 的 class 从 rust 移植到 Z23EEEB4347BDD26BFC6B7EE9AtB7553 不使用 pyo' - __str__ function of class ported from rust to python using pyo3 doesn't get used in print 如何使用 PyO3 构建混合 Python Rust 包 - How to structure a mixed Python Rust package with PyO3 使用 `pyo3` 从 Rust 到 Python 返回 `bytes` 的这 4 种方法有什么区别? - What are the differences between these 4 methods of returning `bytes` from Rust to Python using `pyo3`?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM