Rust日志记录库pyo3-pylogger的使用:Python与Rust无缝集成的日志记录解决方案
pyo3-pylogger
pyo3-pylogger 是一个为嵌入Python应用的pyo3项目提供日志记录的库,它使用Python的logging
模块。
特性
- 将Python的
logging
模块与Rust的log
crate集成 - 通过logging的
extra
字段支持结构化日志记录(需要kv
或tracing-kv
特性) - 与Rust的
tracing
库集成(需要tracing
特性)
使用示例
use log::{info, warn};
use pyo3::{ffi::c_str, prelude::*};
fn main() {
// 使用Python logger注册主机处理器,提供logger目标
pyo3_pylogger::register("example_application_py_logger");
// 初始化logger
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();
// 展示Rust中的logger工作
info!("Just some normal information!");
warn!("Something spooky happened!");
// 让pyo3设置嵌入式Python解释器
pyo3::prepare_freeththreaded_python();
Python::with_gil(|py| {
// Python代码现在可以像往常一样`import logging`
py.run(
c_str!(
r#"
import logging
logging.getLogger().setLevel(0)
logging.debug('DEBUG')
logging.info('INFO')
logging.warning('WARNING')
logging.error('ERROR')
logging.getLogger('foo.bar.baz').info('INFO')"#
),
None,
None,
)
.unwrap();
})
}
输出
[2025-03-28T01:12:29Z INFO helloworld] Just some normal information!
[2025-03-28T01:12:29Z WARN helloworld] Something spooky happened!
[2025-03-28T01:12:29Z DEBUG example_application_py_logger] DEBUG
[2025-03-28T01:12:29Z INFO example_application_py_logger] INFO
[2025-03-28T01:12:29Z WARN example_application_py_logger] WARNING
[2025-03-28T01:12:29Z ERROR example_application_py_logger] ERROR
[2025-03-28T01:12:29Z INFO example_application_py_logger::foo::bar::baz] INFO
结构化日志记录
要启用结构化日志记录支持,在Cargo.toml
中添加kv
特性:
[dependencies]
pyo3-pylogger = { version = "0.4", features = ["kv"] }
然后可以使用Python的extra
参数传递结构化数据:
logging.info("Processing order", extra={"order_id": "12345", "amount": 99.99})
在Rust中使用结构化日志订阅者时,这些键值对将被正确捕获,例如:
[2025-03-28T01:12极客时间
29Z INFO example_application_py_logger] Processing order order_id=12345 amount=99.99
Tracing支持
要启用与Rust的tracing
库集成,在Cargo.toml
中添加tracing
特性:
[dependencies]
pyo3-pylogger = { version = "0.4", default-features = false, features = ["tracing"] }
启用tracing
特性后,Python日志将被转发到活跃的tracing订阅者:
use tracing::{info, warn};
use pyo3::{ffi::c_str, prelude::*};
fn main() {
// 使用Python logger注册tracing处理器
pyo3_pylogger::register_tracing("example_application_py_logger");
// 初始化tracing订阅者
tracing_subscriber::fmt::init();
// 来自Rust的tracing事件
info!("Tracing information from Rust");
// Python日志将被tracing订阅者捕获
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
py.run(
c_str!(
r#"
import logging
logging.getLogger().setLevel极客时间
(0)
logging.info('This will be captured by tracing')"#
),
None,
None,
)
.unwrap();
})
}
使用Tracing的结构化数据
tracing
特性自动支持Python的extra
字段用于结构化数据。然而,KV字段被json序列化,不作为tracing属性可用。这是tracing
库的限制,不是本crate特有的。
特性标志
kv
: 通过Python的extra
字段启用结构化日志记录支持。这为log
crate的键值系统添加了支持。tracing
: 启用与Rust的tracing
库的集成。tracing-kv
: 通过Python的extra
字段启用结构化日志记录支持,并与Rust的tracing
库集成。
完整示例
下面是一个结合了基本日志记录和结构化日志记录的完整示例:
use log::{info, warn};
use pyo3::{ffi::c_str, prelude::*};
fn main() {
// 注册Python日志处理器
pyo3_pylogger::register("my_app_logger");
// 初始化env_logger
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
// Rust日志示例
info!("Starting the application");
warn!("This is a warning from Rust");
// 初始化Python解释器
pyo3::prepare_freethreaded_python();
Python::with_gil(|py| {
// 运行Python代码
py.run(
c_str!(
r#"
import logging
# 设置日志级别
logging.basicConfig(level=logging.DEBUG)
# 普通日志
logging.debug('Debug message from Python')
logging.info('Info message from Python')
logging.warning('Warning message from Python')
logging.error('Error message from Python')
# 结构化日志
logging.info("User login", extra={"username": "john_doe", "ip": "192.168.1.1"})
logging.warning("Payment processed", extra={"amount": 99.99, "currency": "USD"})
# 模块特定日志
module_logger = logging.getLogger('my_app.module')
module_logger.info('Module specific message')
"#
),
None,
None,
)
.unwrap();
});
info!("Application finished");
}
这个示例展示了:
- Rust和Python之间的日志集成
- Python中的结构化日志记录
- 模块特定的日志记录
- 不同日志级别的使用
输出将包含来自Rust和Python的日志消息,包括结构化数据。
1 回复
Rust日志记录库pyo3-pylogger的使用:Python与Rust无缝集成的日志记录解决方案
pyo3-pylogger
是一个基于PyO3的Rust日志记录库,它允许Rust代码使用Python的日志系统进行日志记录,实现了Python和Rust之间的无缝日志集成。
主要特性
- 将Rust的日志记录转发到Python的日志系统
- 完全兼容Python的标准日志配置
- 支持所有标准日志级别
- 保持日志格式和处理器的一致性
安装方法
在Cargo.toml中添加依赖:
[dependencies]
pyo3-pylogger = "0.3"
log = "0.4"
pyo3 = { version = "0.18", features = ["extension-module"] }
基本使用方法
1. 初始化日志记录器
首先需要在Rust中初始化pylogger:
use pyo3_pylogger::PyLogger;
use log::LevelFilter;
#[pyfunction]
pub fn init_logging(py: Python) -> PyResult<()> {
PyLogger::new(py)
.with_log_level(LevelFilter::Info)
.install()?;
Ok(())
}
2. 在Python中调用
import your_rust_module
# 初始化日志
your_rust_module.init_logging()
# 配置Python日志
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
3. 在Rust中记录日志
use log::{info, warn, error};
pub fn do_something() {
info!("This is an info message from Rust");
warn!("This is a warning from Rust");
error!("This is an error from Rust");
}
高级用法
自定义日志记录器名称
PyLogger::new(py)
.with_logger_name("my_rust_module")
.install()?;
设置不同的日志级别
PyLogger::new(py)
.with_log_level(LevelFilter::Debug)
.install()?;
在Python中获取Rust日志
def test_rust_logging():
import logging
logger = logging.getLogger('my_rust_module')
# 添加处理器
handler = logging.StreamHandler()
formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
# 调用Rust函数
your_rust_module.do_something()
完整示例
Rust部分 (lib.rs)
use pyo3::prelude::*;
use pyo3_pylogger::PyLogger;
use log::{info, warn, error, LevelFilter};
#[pyfunction]
pub fn init_logging(py: Python) -> PyResult<()> {
PyLogger::new(py)
.with_logger_name("rust_component")
.with_log_level(LevelFilter::Debug)
.install()?;
Ok(())
}
#[pyfunction]
pub fn perform_calculation(value: i32) -> i32 {
info!("Starting calculation with value: {}", value);
if value < 0 {
warn!("Negative value provided, might cause issues");
}
let result = value * 2;
info!("Calculation complete, result: {}", result);
result
}
#[pymodule]
fn rust_logging(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(init_logging, m)?)?;
m.add_function(wrap_pyfunction!(perform_calculation, m)?)?;
Ok(())
}
Python部分
import logging
from rust_logging import init_logging, perform_calculation
# 配置日志
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
# 初始化Rust日志
init_logging()
# 使用Rust函数
result = perform_calculation(42)
print(f"Result: {result}")
# 测试错误情况
perform_calculation(-5)
注意事项
- 确保在调用任何Rust日志记录之前初始化PyLogger
- Rust和Python的日志级别是独立的,需要在两边都进行适当配置
- 在异步上下文中使用时需要注意线程安全
- 大型日志消息可能会影响性能,建议在生产环境中适当调整日志级别
通过pyo3-pylogger
,你可以实现Python和Rust代码之间的统一日志管理,简化了混合应用的日志记录和调试过程。