docs: Link to pyo3-log in README and the guide

Show how one can log from Rust through the Python's logging facilities.

Related to #1016.
This commit is contained in:
Michal 'vorner' Vaner 2020-07-19 08:37:10 +02:00
parent 41b35b84ca
commit e6dd2d980f
No known key found for this signature in database
GPG Key ID: F700D0C019E4C66F
3 changed files with 70 additions and 0 deletions

View File

@ -137,6 +137,7 @@ about this topic.
* [pyo3-built](https://github.com/PyO3/pyo3-built) _Simple macro to expose metadata obtained with the [`built`](https://crates.io/crates/built) crate as a [`PyDict`](https://pyo3.github.io/pyo3/pyo3/struct.PyDict.html)_
* [rust-numpy](https://github.com/PyO3/rust-numpy) _Rust binding of NumPy C-API_
* [dict-derive](https://github.com/gperinazzo/dict-derive) _Derive FromPyObject to automatically transform Python dicts into Rust structs_
* [pyo3-log](https://github.com/vorner/pyo3-log) _Bridge from Rust to Python logging_
## Examples

View File

@ -16,3 +16,4 @@
- [Appendix A: PyO3 and rust-cpython](rust_cpython.md)
- [Appendix B: Migration Guide](migration.md)
- [Appendix C: Trait bounds](trait_bounds.md)
- [Appendix D: Logging](logging.md)

68
guide/src/logging.md Normal file
View File

@ -0,0 +1,68 @@
# Logging
It is desirable if both the Python and Rust parts of the application end up
logging using the same configuration into the same place.
This section of the guide briefly discusses how to connect the two languages'
logging ecosystems together. The recommended way for Python extension modules is
to configure Rust's logger to send log messages to Python using the `pyo3-log`
crate. For users who want to do the opposite and send Python log messages to
Rust, see the note at the end of this guide.
## Using `pyo3-log` to send Rust log messages to Python
The [pyo3-log] crate allows sending the messages from the Rust side to Python's
[logging] system. This is mostly suitable for writing native extensions for
Python programs.
Use [`pyo3_log::init`][init] to install the logger in its default configuration.
It's also possible to tweak its configuration (mostly to tune its performance).
```rust
use log::info;
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
#[pyfunction]
fn log_something() {
// This will use the logger installed in `my_module` to send the `info`
// message to the Python logging facilities.
info!("Something!");
}
#[pymodule]
fn my_module(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
// A good place to install the Rust -> Python logger.
pyo3_log::init();
m.add_wrapped(wrap_pyfunction!(log_something))?;
Ok(())
}
```
Then it is up to the Python side to actually output the messages somewhere.
```python
import logging
import my_module
FORMAT = '%(levelname)s %(name)s %(asctime)-15s %(filename)s:%(lineno)d %(message)s'
logging.basicConfig(format=FORMAT)
logging.getLogger().setLevel(logging.INFO)
my_module.log_something()
```
It is important to initialize the Python loggers first, before calling any Rust
functions that may log. This limitation can be worked around if it is not
possible to satisfy, read the documentation about [caching].
## The Python to Rust direction
To best of our knowledge nobody implemented the reverse direction yet, though it
should be possible. If interested, the `pyo3` community would be happy to
provide guidance.
[logging]: https://docs.python.org/3/library/logging.html
[pyo3-log]: https://crates.io/crates/pyo3-log
[init]: https://docs.rs/pyo3-log/*/pyo3_log/fn.init.html
[caching]: https://docs.rs/pyo3-log/*/pyo3_log/#performance-filtering-and-caching