pyo3

Macro py_run

Source
macro_rules! py_run {
    ($py:expr, $($val:ident)+, $code:literal) => { ... };
    ($py:expr, $($val:ident)+, $code:expr) => { ... };
    ($py:expr, *$dict:expr, $code:literal) => { ... };
    ($py:expr, *$dict:expr, $code:expr) => { ... };
}
Expand description

A convenient macro to execute a Python code snippet, with some local variables set.

§Panics

This macro internally calls Python::run_bound and panics if it returns Err, after printing the error to stdout.

If you need to handle failures, please use Python::run_bound instead.

§Examples

use pyo3::{prelude::*, py_run, types::PyList};

Python::with_gil(|py| {
    let list = PyList::new(py, &[1, 2, 3])?;
    py_run!(py, list, "assert list == [1, 2, 3]");
})

You can use this macro to test pyfunctions or pyclasses quickly.

use pyo3::{prelude::*, py_run};

#[pyclass]
#[derive(Debug)]
struct Time {
    hour: u32,
    minute: u32,
    second: u32,
}

#[pymethods]
impl Time {
    fn repl_japanese(&self) -> String {
        format!("{}時{}分{}秒", self.hour, self.minute, self.second)
    }
    #[getter]
    fn hour(&self) -> u32 {
        self.hour
    }
    fn as_tuple(&self) -> (u32, u32, u32) {
        (self.hour, self.minute, self.second)
    }
}

Python::with_gil(|py| {
    let time = Py::new(py, Time {hour: 8, minute: 43, second: 16}).unwrap();
    let time_as_tuple = (8, 43, 16);
    py_run!(py, time time_as_tuple, r#"
        assert time.hour == 8
        assert time.repl_japanese() == "8時43分16秒"
        assert time.as_tuple() == time_as_tuple
    "#);
});

If you need to prepare the locals dict by yourself, you can pass it as *locals.

use pyo3::prelude::*;
use pyo3::types::IntoPyDict;

#[pyclass]
struct MyClass;

#[pymethods]
impl MyClass {
    #[new]
    fn new() -> Self {
        MyClass {}
    }
}

Python::with_gil(|py| {
    let locals = [("C", py.get_type::<MyClass>())].into_py_dict(py)?;
    pyo3::py_run!(py, *locals, "c = C()");
})