You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让pybind11静态只读属性的文档字符串在Python中显示?

问题:pybind11绑定的Logger类静态属性文档在Python3.6的help中不显示

我用pybind11将C++的Logger类绑定到Python,代码中给静态只读属性传递了文档字符串,但在Python3.6中执行help(Logger)时,这些属性的描述为空。绑定代码如下:

py::class_<Logger> logger(m, "Logger");
logger.doc() = "class docstring";
logger.def("setLevels", [](uint16_t levels)
    {
        LoggerInstance.setLevels(levels);
    },
    R"(
        Turns on/off different logging levels
        Parameters
        * levels Logging level flags
    )"
);

//expose values as constant fields
logger.def_property_readonly_static("LOG_NONE", [](py::object /* self */){return LOG_NONE;}, "no log level turned on");
logger.def_property_readonly_static("LOG_INFO", [](py::object /* self */){return LOG_INFO;}, "info level logs turned on");
logger.def_property_readonly_static("LOG_DEBUG", [](py::object /* self */){return LOG_DEBUG;}, "debug level logs turned on");
logger.def_property_readonly_static("LOG_WARN", [](py::object /* self */){return LOG_WARN;}, "warning logs turned on");
logger.def_property_readonly_static("LOG_ERROR", [](py::object /* self */){return LOG_ERROR;}, "error logs turned on");
解决方案

在Python3.6及更早版本中,pybind11的def_property_readonly_static方法无法正确将文档字符串关联到属性的__doc__字段,导致help输出中没有描述。可以通过以下两种方式解决:

方法1:手动为静态属性设置文档字符串

先通过attr将常量添加为Logger类的属性,再调用pybind11的内部工具函数为属性设置文档。注意:如果是整数等内置类型实例,Python不允许直接修改其__doc__,这种情况下建议改用方法2。

修改后的代码:

py::class_<Logger> logger(m, "Logger");
logger.doc() = "class docstring";
logger.def("setLevels", [](uint16_t levels)
    {
        LoggerInstance.setLevels(levels);
    },
    R"(
        Turns on/off different logging levels
        Parameters
        * levels Logging level flags
    )"
);

// 直接添加静态属性到类
logger.attr("LOG_NONE") = LOG_NONE;
logger.attr("LOG_INFO") = LOG_INFO;
logger.attr("LOG_DEBUG") = LOG_DEBUG;
logger.attr("LOG_WARN") = LOG_WARN;
logger.attr("LOG_ERROR") = LOG_ERROR;

// 手动设置每个属性的文档字符串
py::detail::set_docstring(logger.attr("LOG_NONE").ptr(), "no log level turned on");
py::detail::set_docstring(logger.attr("LOG_INFO").ptr(), "info level logs turned on");
py::detail::set_docstring(logger.attr("LOG_DEBUG").ptr(), "debug level logs turned on");
py::detail::set_docstring(logger.attr("LOG_WARN").ptr(), "warning logs turned on");
py::detail::set_docstring(logger.attr("LOG_ERROR").ptr(), "error logs turned on");

方法2:改用枚举类型绑定(推荐)

将日志级别定义为C++枚举,通过pybind11的enum_绑定为Python枚举。枚举成员的文档字符串会被Python的help系统正确识别,同时语义更清晰,代码可维护性更强。

步骤1:在C++中定义枚举

enum class LogLevel : uint16_t {
    LOG_NONE = 0,
    LOG_INFO = 1 << 0,
    LOG_DEBUG = 1 << 1,
    LOG_WARN = 1 << 2,
    LOG_ERROR = 1 << 3
};

步骤2:绑定枚举并关联到Logger类

// 绑定枚举类型
py::enum_<LogLevel>(m, "LogLevel")
    .value("LOG_NONE", LogLevel::LOG_NONE, "no log level turned on")
    .value("LOG_INFO", LogLevel::LOG_INFO, "info level logs turned on")
    .value("LOG_DEBUG", LogLevel::LOG_DEBUG, "debug level logs turned on")
    .value("LOG_WARN", LogLevel::LOG_WARN, "warning logs turned on")
    .value("LOG_ERROR", LogLevel::LOG_ERROR, "error logs turned on")
    .export_values();

// 绑定Logger类
py::class_<Logger> logger(m, "Logger");
logger.doc() = "class docstring";
logger.def("setLevels", [](uint16_t levels)
    {
        LoggerInstance.setLevels(static_cast<uint16_t>(levels));
    },
    R"(
        Turns on/off different logging levels
        Parameters
        * levels Logging level flags (can use LogLevel enum values)
    )"
);

// 可选:将枚举成员附加到Logger类,保持原有调用方式
logger.attr("LOG_NONE") = LogLevel::LOG_NONE;
logger.attr("LOG_INFO") = LogLevel::LOG_INFO;
logger.attr("LOG_DEBUG") = LogLevel::LOG_DEBUG;
logger.attr("LOG_WARN") = LogLevel::LOG_WARN;
logger.attr("LOG_ERROR") = LogLevel::LOG_ERROR;

这样无论是help(LogLevel)还是help(Logger.LOG_NONE),都能正确显示对应的文档字符串。

内容的提问来源于stack exchange,提问作者G. B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 05:48:22