如何配置pybind11模块中使用的spdlog记录器



我在使用pybind11创建Python绑定的各种c++库中使用spdlog。

现在我想知道是否有一种很好的方法可以从Python端配置这些日志记录器(主要是级别和格式)。

目前,我正在为构造函数中的每个类创建一个单独的记录器(logger_是一个类成员):

MyClass::MyClass()
{
logger_ = spdlog::get(LOGGER_NAME);
if (!logger_)
{
logger_ = spdlog::stderr_color_mt(LOGGER_NAME);
}
logger_->debug("Logger is set up");
}

现在我可以使用MyClass,它将创建并使用默认设置的记录器。如果我想改变这一点,我可以在创建类之前创建一个具有适当名称的记录器:

auto logger = spdlog::stdout_color_st(MyClass::LOGGER_NAME);
logger->set_level(spdlog::level::debug);
logger->set_pattern("[%l] %n: %v");
MyClass c;

然而,当使用MyClass的Python绑定时,我找不到一个好的方法来做到这一点。我看到已经有一个Python包绑定了spdlog,所以我尝试了以下操作:

import spdlog
logger = spdlog.ConsoleLogger(MyClass.LOGGER_NAME)
logger.set_level(spdlog.LogLevel.DEBUG)
logger.set_pattern("[%l] %n: %v")
c = MyClass()

然而,这并不影响MyClass内部使用的记录器(我假设Python包中的spdlog实例与我的c++代码中的spdlog实例之间没有连接)。

那么长话短说:有没有一种方法,我可以配置在c++代码中使用的记录器从Python端?如果有一种方法无需手动将记录器传递给每个类的构造函数,那就太好了。但我不确定这是否可能?

我没有广泛使用python绑定,但请参阅文档,特别是注释2:

注意2:手动创建的记录器(即您直接构建的记录器)不会自动注册,也不会被get("...")调用找到。

如果你想注册这样的记录器,使用register_logger(...)函数:

spdlog::register_logger(my_logger);
...
auto the_same_logger = spdlog::get("mylogger");

假设register_logger(...)在python绑定中公开,您需要注册您创建的记录器,以便您的类可以看到它。

jwm的回答为我指出了一个可行的解决方案。记录器可以在Python端创建,并通过在该模块中绑定spdlog::register_logger()来注册包含c++类的模块。

  1. 在绑定MyClass的模块中添加spdlog::register_logger()的绑定。因此,绑定的代码看起来像这样:
    PYBIND11_MODULE(mylib, m)
    {
    pybind11::class_<MyClass>(m, "MyClass")
    /* ... */;
    m.def("register_logger", &spdlog::register_logger);
    }
    
  2. 在Python代码中,使用该绑定将记录器注册到c++模块:
    import spdlog
    import mylib
    logger = spdlog.ConsoleLogger(mylib.MyClass.LOGGER_NAME)
    logger.set_level(spdlog.LogLevel.DEBUG)
    logger.set_pattern("[%l] %n: %v")
    # register logger with the function from mylib, so it is accessible inside MyClass
    mylib.register_logger(logger.get_underlying_logger())
    c = mylib.MyClass()
    

最新更新