QT C++调用Python模块捕获异常

QT C++调用Python模块捕获异常

在 C++ 中使用 Qt 调用 Python 脚本时,如果 Python 脚本在运行时抛出错误,可以捕获这些错误并在 Qt 中打印错误信息。为此,可以使用 PyErr_Print() 来打印错误信息,或者通过 PyErr_Fetch() 和 PyErr_NormalizeException() 来获取详细的错误信息并在 Qt 中处理。

示例代码

以下是一个示例代码,展示如何在 C++ 中使用 Qt 调用 Python 模块,并捕获和打印 Python 中的错误信息。

C++ Code

#include <Python.h>
#include <iostream>
#include <QString>
#include <QApplication>
#include <QLabel>

void executePythonFunction() {
    Py_Initialize();

    // Import the Python module
    PyObject* moduleName = PyUnicode_DecodeFSDefault("my_module");
    PyObject* module = PyImport_Import(moduleName);
    Py_DECREF(moduleName);

    if (module != nullptr) {
        // Get the function from the module
        PyObject* function = PyObject_GetAttrString(module, "my_function");

        if (function && PyCallable_Check(function)) {
            // Call the function
            PyObject* result = PyObject_CallObject(function, nullptr);

            if (result == nullptr) {
                // Error occurred, print error information
                PyErr_Print();
                
                // Alternatively, fetch and handle the error manually
                PyObject *ptype, *pvalue, *ptraceback;
                PyErr_Fetch(&ptype, &pvalue, &ptraceback);
                PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);

                // Print error type
                if (ptype != nullptr) {
                    PyObject* str_exc_type = PyObject_Repr(ptype);
                    const char* err_type = PyUnicode_AsUTF8(str_exc_type);
                    std::cerr << "Error type: " << err_type << std::endl;
                    Py_XDECREF(str_exc_type);
                }

                // Print error value
                if (pvalue != nullptr) {
                    PyObject* str_exc_value = PyObject_Repr(pvalue);
                    const char* err_value = PyUnicode_AsUTF8(str_exc_value);
                    std::cerr << "Error value: " << err_value << std::endl;
                    Py_XDECREF(str_exc_value);
                }

                // Print traceback
                if (ptraceback != nullptr) {
                    PyObject* traceback_module = PyImport_ImportModule("traceback");
                    PyObject* format_tb_func = PyObject_GetAttrString(traceback_module, "format_exception");
                    PyObject* traceback_list = PyObject_CallFunctionObjArgs(format_tb_func, ptype, pvalue, ptraceback, nullptr);
                    PyObject* traceback_str = PyUnicode_Join(PyUnicode_FromString(""), traceback_list);
                    const char* tb = PyUnicode_AsUTF8(traceback_str);
                    std::cerr << "Traceback: " << std::endl << tb << std::endl;

                    Py_XDECREF(traceback_module);
                    Py_XDECREF(format_tb_func);
                    Py_XDECREF(traceback_list);
                    Py_XDECREF(traceback_str);
                }

                // Clear error indicator
                PyErr_Clear();
            } else {
                // Handle result if needed
                Py_DECREF(result);
            }

            Py_XDECREF(function);
        } else {
            PyErr_Print();
        }

        Py_XDECREF(module);
    } else {
        PyErr_Print();
    }

    Py_Finalize();
}

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // Call the Python function
    executePythonFunction();

    QLabel label("Check the console for Python error messages.");
    label.show();

    return app.exec();
}

Python 代码(my_module.py)

def my_function():
    # Intentionally raise an error for demonstration
    raise ValueError("This is a test error")

代码分析

初始化和导入模块:

使用 Py_Initialize() 初始化 Python 解释器。
使用 PyUnicode_DecodeFSDefault 和 PyImport_Import 导入 Python 模块 my_module。

获取和调用函数:

使用 PyObject_GetAttrString 获取模块中的函数 my_function。
使用 PyObject_CallObject 调用函数。

错误处理:

使用 PyErr_Print() 打印错误信息到标准错误。
或者,使用 PyErr_Fetch 和 PyErr_NormalizeException 获取详细的错误信息,并打印错误类型、错误值和堆栈跟踪。

显示错误信息:

使用标准输出流(std::cerr)在控制台中打印错误信息。

更通用情况

通常,Python 函数在执行过程中可能会遇到各种错误(例如零除错误、文件不存在错误等)。
如果没有主动 raise 异常,可以使用 PyErr_Occurred() 来检查是否有错误发生,然后使用 PyErr_Fetch() 获取详细的错误信息。

C++ 代码

#include <Python.h>
#include <iostream>
#include <QString>
#include <QApplication>
#include <QLabel>

void executePythonFunction() {
    Py_Initialize();

    // Import the Python module
    PyObject* moduleName = PyUnicode_DecodeFSDefault("my_module");
    PyObject* module = PyImport_Import(moduleName);
    Py_DECREF(moduleName);

    if (module != nullptr) {
        // Get the function from the module
        PyObject* function = PyObject_GetAttrString(module, "my_function");

        if (function && PyCallable_Check(function)) {
            // Call the function
            PyObject* result = PyObject_CallObject(function, nullptr);

            if (result == nullptr) {
                // Error occurred, print error information
                PyErr_Print();
                
                // Alternatively, fetch and handle the error manually
                PyObject *ptype, *pvalue, *ptraceback;
                PyErr_Fetch(&ptype, &pvalue, &ptraceback);
                PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);

                // Print error type
                if (ptype != nullptr) {
                    PyObject* str_exc_type = PyObject_Repr(ptype);
                    const char* err_type = PyUnicode_AsUTF8(str_exc_type);
                    std::cerr << "Error type: " << err_type << std::endl;
                    Py_XDECREF(str_exc_type);
                }

                // Print error value
                if (pvalue != nullptr) {
                    PyObject* str_exc_value = PyObject_Repr(pvalue);
                    const char* err_value = PyUnicode_AsUTF8(str_exc_value);
                    std::cerr << "Error value: " << err_value << std::endl;
                    Py_XDECREF(str_exc_value);
                }

                // Print traceback
                if (ptraceback != nullptr) {
                    PyObject* traceback_module = PyImport_ImportModule("traceback");
                    PyObject* format_tb_func = PyObject_GetAttrString(traceback_module, "format_exception");
                    PyObject* traceback_list = PyObject_CallFunctionObjArgs(format_tb_func, ptype, pvalue, ptraceback, nullptr);
                    PyObject* traceback_str = PyUnicode_Join(PyUnicode_FromString(""), traceback_list);
                    const char* tb = PyUnicode_AsUTF8(traceback_str);
                    std::cerr << "Traceback: " << std::endl << tb << std::endl;

                    Py_XDECREF(traceback_module);
                    Py_XDECREF(format_tb_func);
                    Py_XDECREF(traceback_list);
                    Py_XDECREF(traceback_str);
                }

                // Clear error indicator
                PyErr_Clear();
            } else {
                // Handle result if needed
                Py_DECREF(result);
            }

            Py_XDECREF(function);
        } else {
            PyErr_Print();
        }

        Py_XDECREF(module);
    } else {
        PyErr_Print();
    }

    Py_Finalize();
}

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);

    // Call the Python function
    executePythonFunction();

    QLabel label("Check the console for Python error messages.");
    label.show();

    return app.exec();
}

Python 代码(my_module.py)

def my_function():
    x = 1 / 0  # This will raise a ZeroDivisionError
  • PyObject_CallObject(function, nullptr) 调用 Python 函数 my_function。如果在执行过程中发生任何错误,result 将为 nullptr。
    检查和处理错误:
  • 使用 PyErr_Print() 打印错误信息。
  • 使用 PyErr_Fetch() 和 PyErr_NormalizeException() 获取详细的错误信息,并打印错误类型、错误值和堆栈跟踪。
  • 16
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值