Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

日誌

理想情況是應用程式中的 Python 與 Rust 部分都使用相同設定,並將日誌輸出到同一位置。

本節簡要說明如何連結兩種語言的日誌生態系。對於 Python 擴充模組,建議的方式是使用 pyo3-log 軟體箱設定 Rust 的 logger,將日誌訊息送到 Python。若你想反向將 Python 日誌送到 Rust,請見本指南最後的說明。

使用 pyo3-log 將 Rust 日誌訊息送到 Python

pyo3-log 軟體箱允許將 Rust 端訊息傳送到 Python 的 logging 系統。這主要適用於為 Python 程式撰寫原生擴充。

使用 pyo3_log::init 以預設設定安裝 logger。也可以調整其設定(多半用於效能調校)。

#[pyo3::pymodule]
mod my_module {
    use log::info;
    use pyo3::prelude::*;

    #[pyfunction]
    fn log_something() {
        // 這會使用安裝在 `my_module` 的 logger,將 `info`
        // 訊息送到 Python 的 logging 系統。
        info!("Something!");
    }

    #[pymodule_init]
    fn init(m: &Bound<'_, PyModule>) -> PyResult<()> {
        // 安裝 Rust -> Python logger 的好位置。
        pyo3_log::init();
    }
}

接著由 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()

在呼叫任何可能產生日誌的 Rust 函式之前,務必先初始化 Python 的 logger。若無法滿足此限制,仍可用替代方式處理,請閱讀快取相關文件。

Python 到 Rust 的方向

若要讓 Rust 處理 Python 日誌,只需註冊一個 Rust 函式來處理由 Python 核心 logging 模組送出的日誌。

這已由 pyo3-pylogger 軟體箱實作。

use log::{info, warn};
use pyo3::prelude::*;

fn main() -> PyResult<()> {
    // 在 python logger 中註冊主機端處理器,並提供 logger target
    // 這裡的名稱請設定為適合你的應用程式
    pyo3_pylogger::register("example_application_py_logger");

    // 初始化 logger
    env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();

    // 從 Rust 紀錄一些訊息。
    info!("Just some normal information!");
    warn!("Something spooky happened!");

    // 從 Python 紀錄一些訊息
    Python::attach(|py| {
        py.run(
            "
import logging
logging.error('Something bad happened')
",
            None,
            None,
        )
    })
}