I'm working on a videogame in which I'll need to set Rust objects (like, add a button with texture:"", coords:"", text:"", action:""
) from Python files.
I'm using the pyo3 crate to link Python and Rust. I succeed calling Python scripts from my Rust code, but I can't find how to call a Rust function from a Python file.
Rust code that executes my Python script:
fn main() -> PyResult<()> {
let gil = Python::acquire_gil();
let py = gil.python();
let script = fs::read_to_string("deep_hello.py")?;
println!("RUNNING :\n[\n{}]", script);
py.run(&script, None, None)
}
Rust function that I'd like to call from my Python script:
/// hello_from_rust(/)
/// --
///
/// This function prints hello because she is very nice.
#[pyfunction]
fn hello_from_rust() {
println!("Hello from rust from python !");
}
My Python script:
hello_from_rust()
I'm getting this output:
RUNNING :
[
hello_from_rust()
]
Error: PyErr { type: Py(0x7f9cdd1e9580, PhantomData) }
Rust can benefit from Python's ease of use, and Python can benefit from Rust's speed and safety. If you want to use Rust with Python, or Python with Rust, you'll need to have at least passing familiarity with both languages to get the best results.
If I understood your issue correctly, what you're trying to do involves three steps:
hello_from_rust()
deep_hello.py
deep_hello.py
from within Rust.I wasn't able to completely reproduce your issue, but it seems like the root of your problem might be in the first or second step.
From the PyO3 documentation, I would expect hello_from_rust()
to be in a Rust file defining a Python module that looks something like this:
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyfunction]
fn hello_from_rust() {
println!("Hello from rust from python !");
}
#[pymodule]
fn hello_module(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(hello_from_rust));
Ok(())
}
You can build this into a Python module with Cargo (see here; instructions are slightly different depending on your OS) and place the resulting .so
(Linux or MacOS) or .pyd
(Windows) file in the same directory as your Python script.
You have to create a function something along the lines of hello_module
to initialize your Python module. If you don't, your Rust library might still compile, but you won't be able to import hello_from_rust
.
Your deep_hello.py
script should look like this:
import hello_module
hello_module.hello_from_rust()
Making sure that the .so
or .pyd
file is accessible in your PYTHON_PATH
(eg by putting it in the same directory as your script), running deep_hello.py
with Python >= 3.5 should work. (Note that your system Python is probably Python 2, so you might want to create an Anaconda environment with a newer version of Python and work from in there.)
For me, following these steps did the trick.
(ruspy) ruspy $ python deep_hello.py
Hello from rust from python !
Make sure you remember to import hello_module
in your Python script! The PyErr
returned by your py.run(&script, None, None)
makes me wonder if the problem is actually in your Python script, and indeed I would expect hello_from_rust()
without a preceding from deep_hello import *
to produce a NameError
, even if you put together your deep_hello
module correctly.
I'm not totally sure why you want to do this, but you should now be able to run deep_hello.py
from Rust.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With