[DOC] Add Python from Rust section in the guide
This commit is contained in:
parent
35851b7ff9
commit
a344999526
|
@ -121,9 +121,8 @@ fn main_(py: Python) -> PyResult<()> {
|
|||
}
|
||||
```
|
||||
|
||||
If you want to excute one or more statements, you can use
|
||||
[`Python::run`](https://pyo3.rs/master/doc/pyo3/struct.Python.html#method.run)
|
||||
or [`py_run!](https://pyo3.rs/master/doc/pyo3/macro.py_run.htm) macro.
|
||||
Our guide has [a section](https://pyo3.rs/master/python_from_rust.html) with lots of examples
|
||||
about this topic.
|
||||
|
||||
## Examples and tooling
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
- [Python Module](module.md)
|
||||
- [Python Function](function.md)
|
||||
- [Python Class](class.md)
|
||||
- [Call Python from Rust](python_from_rust.md)
|
||||
- [Parallelism](parallelism.md)
|
||||
- [Debugging](debugging.md)
|
||||
- [Advanced Topics](advanced.md)
|
||||
|
|
|
@ -115,9 +115,8 @@ fn main_(py: Python) -> PyResult<()> {
|
|||
}
|
||||
```
|
||||
|
||||
If you want to excute one or more statements, you can use
|
||||
[`Python::run`](https://pyo3.rs/master/doc/pyo3/struct.Python.html#method.run)
|
||||
or [`py_run!](https://pyo3.rs/master/doc/pyo3/macro.py_run.htm) macro.
|
||||
Our guide has [a section](https://pyo3.rs/master/python_from_rust.html) with lots of examples
|
||||
about this topic.
|
||||
|
||||
## Examples and tooling
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
# Call Python functions from Rust
|
||||
|
||||
## Want to run just an expression? Then use eval.
|
||||
|
||||
[`Python::eval`](https://pyo3.rs/master/doc/pyo3/struct.Python.html#method.eval) is
|
||||
a method to execute a [Python expression](https://docs.python.org/3.7/reference/expressions.html)
|
||||
and returns the evaluated value as `PyAny`.
|
||||
|
||||
```rust
|
||||
use pyo3::prelude::*;
|
||||
use pyo3::types::IntoPyDict;
|
||||
|
||||
fn main() -> Result<(), ()> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let result = py.eval("[i * 10 for i in range(5)]", None, None).map_err(|e| {
|
||||
e.print_and_set_sys_last_vars(py);
|
||||
})?;
|
||||
let res: Vec<i64> = result.extract().unwrap();
|
||||
assert_eq!(res, vec![0, 10, 20, 30, 40]);
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
|
||||
## Want to run statements? Then use run.
|
||||
|
||||
[`Python::run`](https://pyo3.rs/master/doc/pyo3/struct.Python.html#method.run)
|
||||
is a method to execute one or more
|
||||
[Python statements](https://docs.python.org/3.7/reference/simple_stmts.html).
|
||||
This method returns nothing, but you can get objects via `locals` dict.
|
||||
|
||||
You can also use the [`py_run!`](https://pyo3.rs/master/doc/pyo3/macro.py_run.html)
|
||||
macro, which is a shorthand for `Python::run`.
|
||||
Since `py_run!` can cause panic, we recommend you to use this macro only for testing
|
||||
your Python extensions quickly.
|
||||
|
||||
```rust
|
||||
use pyo3::{PyObjectProtocol, prelude::*, py_run};
|
||||
# fn main() {
|
||||
#[pyclass]
|
||||
struct UserData {
|
||||
id: u32,
|
||||
name: String,
|
||||
}
|
||||
#[pymethods]
|
||||
impl UserData {
|
||||
fn as_tuple(&self) -> (u32, String) {
|
||||
(self.id, self.name.clone())
|
||||
}
|
||||
}
|
||||
#[pyproto]
|
||||
impl PyObjectProtocol for UserData {
|
||||
fn __repr__(&self) -> PyResult<String> {
|
||||
Ok(format!("User {}(id: {})", self.name, self.id))
|
||||
}
|
||||
}
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let userdata = UserData {
|
||||
id: 34,
|
||||
name: "Yu".to_string(),
|
||||
};
|
||||
let userdata = PyRef::new(py, userdata).unwrap();
|
||||
let userdata_as_tuple = (34, "Yu");
|
||||
py_run!(py, userdata userdata_as_tuple, r#"
|
||||
assert repr(userdata) == "User Yu(id: 34)"
|
||||
assert userdata.as_tuple() == userdata_as_tuple
|
||||
"#);
|
||||
# }
|
||||
```
|
||||
|
||||
## You have a python file or Python function? Then use PyModule.
|
||||
[PyModule](https://pyo3.rs/master/doc/pyo3/types/struct.PyModule.html) also can
|
||||
execute Python codes by calling a function.
|
||||
|
||||
```rust
|
||||
use pyo3::{prelude::*, types::{IntoPyDict, PyModule}};
|
||||
# fn main() -> PyResult<()> {
|
||||
let gil = Python::acquire_gil();
|
||||
let py = gil.python();
|
||||
let activators = PyModule::from_code(py, "
|
||||
def relu(x):
|
||||
return max(0.0, x)
|
||||
|
||||
def leaky_relu(x, slope=0.01):
|
||||
return x if x >= 0 else x * slope
|
||||
", "activators.py", "activators")?;
|
||||
let relu_result: f64 = activators.call1("relu", (-1.0,))?.extract()?;
|
||||
assert_eq!(relu_result, 0.0);
|
||||
let kwargs = [("slope", 0.2)].into_py_dict(py);
|
||||
let lrelu_result: f64 = activators
|
||||
.call("leaky_relu", (-1.0,), Some(kwargs))?
|
||||
.extract()?;
|
||||
assert_eq!(lrelu_result, -0.2);
|
||||
# Ok(()) }
|
||||
```
|
||||
|
||||
|
|
@ -310,6 +310,10 @@ pub mod doc_test {
|
|||
doctest!("../guide/src/function.md", guide_function_md);
|
||||
doctest!("../guide/src/get_started.md", guide_get_started_md);
|
||||
doctest!("../guide/src/module.md", guide_module_md);
|
||||
doctest!(
|
||||
"../guide/src/python_from_rust.md",
|
||||
guide_python_from_rust_md
|
||||
);
|
||||
doctest!("../guide/src/parallelism.md", guide_parallelism_md);
|
||||
doctest!("../guide/src/pypy.md", guide_pypy_md);
|
||||
doctest!("../guide/src/rust_cpython.md", guide_rust_cpython_md);
|
||||
|
|
|
@ -90,6 +90,16 @@ impl<'p> Python<'p> {
|
|||
///
|
||||
/// If `globals` is `None`, it defaults to Python module `__main__`.
|
||||
/// If `locals` is `None`, it defaults to the value of `globals`.
|
||||
///
|
||||
/// # Example:
|
||||
/// ```
|
||||
/// # use pyo3::{types::{PyBytes, PyDict}, prelude::*};
|
||||
/// # let gil = pyo3::Python::acquire_gil();
|
||||
/// # let py = gil.python();
|
||||
/// let result = py.eval("[i * 10 for i in range(5)]", None, None).unwrap();
|
||||
/// let res: Vec<i64> = result.extract().unwrap();
|
||||
/// assert_eq!(res, vec![0, 10, 20, 30, 40])
|
||||
/// ```
|
||||
pub fn eval(
|
||||
self,
|
||||
code: &str,
|
||||
|
|
Loading…
Reference in New Issue