Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PyO3+Polars Expr::AnonymousFunction: Execution (python) deadlocks when function points to python code #8039

Closed
2 tasks done
AnatolyBuga opened this issue Apr 6, 2023 · 2 comments
Labels
bug Something isn't working python Related to Python Polars

Comments

@AnatolyBuga
Copy link
Contributor

AnatolyBuga commented Apr 6, 2023

Polars version checks

  • I have checked that this issue has not already been reported.

  • I have confirmed this bug exists on the latest version of Polars.

Issue description

Updated MRE

I'd like users to define functions in python to be converted into Expr(Anonymous functions) for later use.

However, as soon as I introduce a call to Python::with_gil from inside an AnonymousFunction - the interprete just hangs

Any thoughts would be much appreciated.

Reproducible example

use polars::lazy::dsl::{map_binary, GetOutput};
use polars::prelude::{DataFrame};
use polars::prelude::*;
use pyo3::{pyclass, pymodule, pymethods, Python, types::{PyModule, PyType}, PyResult, PyObject};
use pyo3::prelude::*;

#[pyclass]
pub struct DataSet {
    data: DataFrame
}
#[pymethods]
impl DataSet {
    #[classmethod]
    fn new(_: &PyType) -> Self {

        let data = df!["a" => [1, 2, 3],
         "b" => [4, 5, 6], 
         "c" => ["a", "d", "b"]].unwrap();
        Self{data}
    }

    fn execute(&self, e: &ExprWrapper)  {
        let res = self.data.clone().lazy().with_column(e.e.clone())
            .collect()
            .unwrap();
        dbg!(res);
    }
}

#[pyclass]
pub struct ExprWrapper {
    pub e: Expr
}

#[pyfunction]
fn ultimeasure(pyfnc: PyObject) -> ExprWrapper{
    let functor = move |_: Series, _: Series| { 
        let _ = pyfnc.clone();

        // Here I would convert Series to Python Side Series, call lambda, then result back to Rust Series
        Python::with_gil(move |_| {});
        let srs = Series::new("a", [1,2]);
        Ok(Some(srs))
        };

    let e = map_binary(col("a"), col("b"), functor, GetOutput::from_type(DataType::Float64));
    ExprWrapper{e}
}
#[pymodule]
fn pyo3issue(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<DataSet>()?;
    m.add_wrapped(wrap_pyfunction!(ultimeasure)).unwrap();
    Ok(())
}

!!! Python side, the code I am executing:

import pyo3issue
import polars as pl

def calculator(a: pl.Series, b: pl.Series):
            print("here")
            return a**b

c = pyo3issue.DataSet.new()
m = pyo3issue.ultimeasure(lambda a,b : a**b)
print(c.execute(m))

Expected behavior

I don't understand why this doesn't work. It is very similar to map_mul of py-polars. With only exception that map_mul is a #[pyfunction].

Installed versions

Finally, Cargo.toml:

[lib]
name = "pyo3issue"
# "cdylib" is necessary to produce a shared library for Python to import from.
crate-type = ["cdylib"]

[dependencies]
polars = { version = "0.28.0", features = [
    "lazy"
] }
pyo3-polars = "0.2.0"
polars-arrow = "0.28.0"

[dependencies.pyo3]
version = "0.18.0"
# "abi3-py37" tells pyo3 (and maturin) to build using the stable ABI with minimum Python version 3.7
features = ["abi3-py37"]
@AnatolyBuga AnatolyBuga added bug Something isn't working python Related to Python Polars labels Apr 6, 2023
@AnatolyBuga AnatolyBuga changed the title Execution (python) hangs when function of Expr::AnonymousFunction points to python code PyO3+Polars Expr::AnonymousFunction: Execution (python) hangs when function points to python code Apr 6, 2023
@AnatolyBuga
Copy link
Contributor Author

AnatolyBuga commented Apr 6, 2023

may be I would be able to achieve converting python functions into UDFs with #6325

@AnatolyBuga AnatolyBuga changed the title PyO3+Polars Expr::AnonymousFunction: Execution (python) hangs when function points to python code PyO3+Polars Expr::AnonymousFunction: Execution (python) deadlocks when function points to python code Apr 7, 2023
@AnatolyBuga
Copy link
Contributor Author

What was missing ispy.allow_threads() around .collect()(because this is where functor is actually called. For more details see this thread ).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working python Related to Python Polars
Projects
None yet
Development

No branches or pull requests

1 participant