0

I am writing a python model for heavy calculations in rust using the pyo3 bindings. However, for a rust struct with a variable containing an empty list I cannot append to that variable in python.

Does anybody know how to do this? See below for a MWE ( that I cannot get to work ):

I have a rust file called lib.rs:

// lib.rs

use pyo3::prelude::*;
use std::vec::Vec;

#[pyclass(subclass)]
pub struct TestClass {
    #[pyo3(get)]
    pub id: i32,
    #[pyo3(get, set)]
    pub test_list: Vec<f32>
}

#[pymethods]
impl TestClass {
    #[new]
    pub fn new(id: i32) -> TestClass {
        TestClass{
            id,
            test_list: Vec::new()
        }
    }
}

/// A Python module implemented in Rust.
#[pymodule]
fn test_rust(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<TestClass>()?;
    Ok(())
}

This library is build using the maturin package. When I initiate the TestClass in python that works as expected. However, when I want to append to the class attribute test_list this is not happening. test_list still is an empty list. See for an example below:

from test_rust import TestClass

foo = TestClass(1)

print(foo.test_list) # output: []
foo.test_list.append(2.3)
print(foo.test_list) # output: [] - expected: [2.3]

The pyo3 documentation stated that the types Vec<T> and list[T] are accepted. However, this does not work.

Any help would be very much appreciated.

westr
  • 569
  • 5
  • 17
  • Having no experience with pyo3 whatsoever, but just guessing: What happens if you remove the `get` from `#[pyo3(get, set)]`, or if you remove that annotation entirely? – mkrieger1 Dec 23 '22 at 14:29
  • I think @mkrieger1 is right ... accessing `.test_list` like this **copies** it. If you do `my_list = foo.test_list`, followed by `my_list.append(2.3)` and `print(my_list)`, you will see that it actually worked, it just isn't the same list as in `foo` any more. This is due to an incompatibility with Rust's and Python's ownership models. – Finomnis Dec 23 '22 at 14:33
  • I would also experiment with replacing `Vec` by `PyList`. – mkrieger1 Dec 23 '22 at 14:35
  • The thing is that I need to access the `Vec` in both rust (functions to be implemented) and python. – westr Dec 23 '22 at 14:44
  • Does this answer your question? [Return reference to member field in PyO3](https://stackoverflow.com/questions/69665304/return-reference-to-member-field-in-pyo3) – Finomnis Dec 24 '22 at 08:28
  • Also very relevant: https://stackoverflow.com/questions/73159723/rust-py03-how-to-get-reference-to-struct-member – Finomnis Dec 25 '22 at 16:27
  • Thanks for your comments so far. Based on the suggested questions, I managed to write a function in rust that appends to `Vec` by using a wrapper around it, such that I can do `foo.append(2.3)`. This gives the desired result, but since I replace my python code by rust gradually, I actually need be able to do `foo.test_list.append(2.3)`. Any ideas? – westr Jan 04 '23 at 13:17

0 Answers0