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

如何通过pybind11获取Python调用C++函数的代码行号

获取Python调用C++函数的代码行号解决方案

要在pybind11实现的C++日志类中获取Python调用处的文件名和行号,核心是利用Python的栈帧API提取调用上下文信息,具体实现步骤如下:

1. 补充必要头文件

首先添加pybind11相关头文件以及日志处理所需的标准库头:

#include <pybind11/pybind11.h>
#include <pybind11/eval.h>
#include <string>
#include <memory>
#include <chrono>
#include <iomanip>
#include <fstream>

namespace py = pybind11;

2. 修改日志类的log方法

在log方法中通过Python的sys._getframe()获取调用栈帧,从中提取文件名和行号,同时处理非Python调用的异常情况:

class PythonLogger
{
public:
    PythonLogger(const std::string& filename) : log_file(filename, std::ios::app) { /* 打开日志文件 */ }
    ~PythonLogger() { if (log_file.is_open()) log_file.close(); }
    
    void log(const std::string& msg) {
        std::string filename = "unknown";
        int line_number = 0;

        try {
            // 获取上一级栈帧(参数1跳过当前C++函数对应的Python包装帧)
            py::object frame = py::module_::import("sys").attr("_getframe")(1);
            filename = frame.attr("f_code").attr("co_filename").cast<std::string>();
            line_number = frame.attr("f_lineno").cast<int>();
        } catch (const py::error_already_set&) {
            // 无法获取帧信息时,清除Python错误状态并使用默认值
            PyErr_Clear();
        }

        // 生成格式化时间字符串
        auto now = std::chrono::system_clock::now();
        std::time_t now_time = std::chrono::system_clock::to_time_t(now);
        std::string time_str = std::ctime(&now_time);
        if (!time_str.empty() && time_str.back() == '\n') {
            time_str.pop_back();
        }

        // 格式化日志内容并写入文件
        std::string log_entry = "[" + time_str + "] [" + filename + ":" + std::to_string(line_number) + "]: " + msg + "\n";
        if (log_file.is_open()) {
            log_file << log_entry;
            log_file.flush();
        }
    }

private:
    std::ofstream log_file; // 替换为你的文件类,此处用标准库ofstream示例
};
typedef std::shared_ptr<PythonLogger> PythonLoggerPtr;

3. 修正pybind11模块绑定

确保Python的debug方法正确映射到C++的log方法,同时添加构造函数绑定:

PYBIND11_EMBEDDED_MODULE(PythonLogger, m) {
    py::class_<PythonLogger, PythonLoggerPtr>(m, "Logger")
        .def(py::init<const std::string&>())
        .def("debug", &PythonLogger::log);
}

4. 验证效果

运行嵌入式Python程序后,script.py中第2行调用logger.debug("debug message")会生成符合预期的日志:

[Wed Oct 11 14:30:00 2024] [script.py:2]: debug message

关键说明

  • sys._getframe(1):获取调用当前函数的上一级栈帧,参数1跳过C++函数对应的Python包装层,直接指向Python代码的调用位置。
  • 异常处理:如果log被C++代码直接调用,sys._getframe()会抛出错误,此时捕获异常并清除Python错误状态,避免影响后续执行。

内容的提问来源于stack exchange,提问作者Eliv_

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 06:55:07