I'm a complete Rust newbie, Please help me.
(The book Rust in Action guided me to visit here. It said here's the fantastic community always welcomes newbies.)
Please don't get me wrong since this is my last resort after struggling in several hours for googling any solutions.
I'm tring to use Tauri to build a web-based GUI application.
The problem is the existing backend module is a big python module which is about 3,000 lines of code.
After struggling in several hours, I happened to find this solution that works perfectly.
But I realized the module initialization with PyModule::from_code(py, PY_APP, "", "") might be time-consuming since it doesn't have any cache mechanism. (I checked it from the source code)
// Simlified example with `call0`
fn pychart() -> PyResult<String> {
let py_foo = include_str!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/python_app/utils/foo.py"
));
Python::with_gil(|py| {
let module = PyModule::from_code(py, PY_APP, "", "")?;
let result = module.getattr("chart")?.call0()?;
let value = result.extract()?;
Ok(value)
})
}
So, I finally started to find any way to share the initialized PyModule object around any rust functions which need to call python function like this, (but it failed I know the code doesn't make sense )
You just need to use the Py type to convert a GIL scoped reference to a longer lived value. Then you can acquire the GIL when you need to use the reference again.
Here's an example of doing that
use pyo3::{types::PyModule, Py, Python};
fn main() {
// Initialize the module once
let module = Python::with_gil(|py| {
let module: Py<PyModule> = PyModule::from_code(
py,
"\
print(\"starting\");
def function():
print(\"Hi\")
",
"fake.py",
"fake",
)
// Panic on any errors since this is an example
.unwrap()
// Convert the GIL scoped reference into a long lived reference.
.into();
module
});
// Pass a reference to the GIL independent python object reference to the function.
// This allows us to avoid re-initializing the module over and over.
call(&module);
// Second call shouldn't print "starting" again, since the module is already initialized
call(&module);
}
fn call(module: &Py<PyModule>) {
Python::with_gil(|py| {
// Convert the GIL-independent reference into a usable reference scoped to the GIL lock closure
let module = module.as_ref(py);
// Get the function and call it.
module.getattr("function").unwrap().call0().unwrap();
});
}