address feedback in review #2678

This commit is contained in:
David Hewitt 2023-01-05 21:39:41 +00:00
parent e52dbc907d
commit 8651d3b0e8
1 changed files with 37 additions and 38 deletions

View File

@ -245,20 +245,42 @@ def leaky_relu(x, slope=0.01):
# } # }
``` ```
### Want to embed Python in Rust with exposed modules? ### Want to embed Python in Rust with additional modules?
Internally Python maintains the `sys.modules` dict. Python maintains the `sys.modules` dict as a cache of all imported modules.
An import in Python is simply a lookup into this dict. An import in Python will first attempt to lookup the module from this dict,
and if not present will use various strategies to attempt to locate and load
the module.
It is necessary to insert the new module into the dict The [`append_to_inittab`]({{*PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html)
before it is exposed to Python. There are two ways of macro can be used to add additional `#[pymodule]` modules to an embedded
doing this. Python interpreter. The macro **must** be invoked _before_ initializing Python.
* manually inserting into `sys.modules` As an example, the below adds the module `foo` to the embedded interpreter:
* using [`append_to_inittab`]({{*PYO3_DOCS_URL}}/pyo3/macro.append_to_inittab.html) macro
```rust
use pyo3::prelude::*;
Example using `sys.modules` #[pyfunction]
fn add_one(x: i64) -> i64 {
x + 1
}
#[pymodule]
fn foo(_py: Python<'_>, foo_module: &PyModule) -> PyResult<()> {
foo_module.add_function(wrap_pyfunction!(add_one, foo_module)?)?;
Ok(())
}
fn main() -> PyResult<()> {
pyo3::append_to_inittab!(foo);
Python::with_gil(|py| Python::run(py, "import foo; foo.add_one(6)", None, None))
}
```
If `append_to_inittab` cannot be used due to constraints in the program,
an alternative is to create a module using [`PyModule::new`]
and insert it manually into `sys.modules`:
```rust ```rust
use pyo3::prelude::*; use pyo3::prelude::*;
@ -288,32 +310,6 @@ fn main() -> PyResult<()> {
} }
``` ```
Example using [`append_to_inittab`](https://docs.rs/pyo3/latest/pyo3/macro.append_to_inittab.html):
**WARNING** You must call `append_to_inittab` _before_ initializing Python.
```rust
use pyo3::prelude::*;
#[pyfunction]
fn add_one(x: i64) -> i64 {
x + 1
}
#[pymodule]
fn foo(_py: Python, foo_module: &PyModule) -> PyResult<()> {
foo_module.add_function(wrap_pyfunction!(add_one, foo_module)?)?;
Ok(())
}
fn main() -> PyResult<()> {
pyo3::append_to_inittab!(foo);
Python::with_gil(|py| Python::run(py, "import foo; foo.add_one(6)", None, None))
}
```
### Include multiple Python files ### Include multiple Python files
You can include a file at compile time by using You can include a file at compile time by using
@ -331,9 +327,9 @@ Example directory structure:
├── Cargo.lock ├── Cargo.lock
├── Cargo.toml ├── Cargo.toml
├── python_app ├── python_app
   ├── app.py ├── app.py
   └── utils └── utils
   └── foo.py └── foo.py
└── src └── src
└── main.rs └── main.rs
``` ```
@ -464,3 +460,6 @@ class House(object):
}) })
} }
``` ```
[`PyModule::new`]: {{#PYO3_DOCS_URL}}/pyo3/types/struct.PyModule.html#method.new