2

I have a function that accepts a Python list. I expect the list to be made of strings. How do I extract them?

fn f(list: &PyList) -> PyResult<SomeClass> {
    for obj in list.iter() {
        let rust_string = PyString::from_object(obj, "ASCII", "strict")?.to_string()?;
        // fails with `TypeError: decoding str is not supported`
        
        if PyString::is_exact_instance(obj) {
            let py_str: PyString = unsafe {std::mem::transmute(str)};
            let rust_str = py_str.to_string()?;
            // panics with failed assertion in PyString.as_bytes()
        }
    }
    // ...
}

// Python call site
f(["string1", "string2"])

Software versions: Python 3.7, nightly Rust 1.33.0, pyo3 0.5.2.

trent
  • 25,033
  • 7
  • 51
  • 90
user7810882
  • 223
  • 1
  • 4
  • 14
  • 1
    From a quick look at the documentation, it looks like downcasting is done using the [`PyObject::extract()` method](https://docs.rs/pyo3/0.5.2/pyo3/struct.PyObject.html#method.extract), something like `let rust_str: &str = obj.extract(py)?`, where `py` is the [GIL wrapper](https://docs.rs/pyo3/0.5.2/pyo3/python/struct.Python.html). I haven't tried it, though. – Sven Marnach Dec 27 '18 at 21:39
  • On second look, the [example on the start page of the documentation](https://docs.rs/pyo3/0.5.2/pyo3/index.html#example-1) looks even more promising – you can use the `pyfn` attribute to have the conversion from Python to Rust types handled for you implicitly. – Sven Marnach Dec 27 '18 at 21:43
  • Thanks. The first one works. `let py_str: &PyString = obj.extract()?;`. `let str = py_str.to_string()?;` – user7810882 Dec 27 '18 at 21:49

1 Answers1

0
fn f(list: &PyList) -> PyResult<SomeClass> {
    for i in list.iter() {
        let mut str_2 = match i.extract() {
            Ok(val) =>{
                val
            },
            Err(why) => {
                panic!("{:}", why);
                String::new()
            }
        };
        
        println!("{}", str_2);
    }
    // ...
}

I guess that's the answer cause unwrap is not working and the python list might have any object like number or string or even dict. For that case, Fail-safe will be checking of each and every data type which pyo3 has in it.