8

我在我的应用程序中嵌入了 python 解释器。PyRun_String()我用它来使用API运行 python 脚本。PyErr_Fetch()如果遇到错误/异常,我可以获取错误信息。这给了我异常类型、异常值和异常回溯。然后我从回溯中找到原始错误的行号。但是,如果出现语法错误,我不会得到任何类型的回溯。有谁知道如何在没有回溯的情况下检索行号..?有没有办法使用异常类型或异常值来检索它..?

Python 文档指出:

此类的实例具有属性文件名、行号、偏移量和文本,以便更轻松地访问详细信息。异常实例的 str() 只返回消息。

如何在嵌入式 python 中检索 SyntaxError 的文件名和 lineno 属性..?

任何帮助将不胜感激。提前致谢。


谢谢你的建议布雷特。但我已经尝试过使用 PyObject_GetAttr()。

请参阅下面我用于测试目的的示例代码。

int main(int argc, char** argv)
{
    Py_Initialize();

    // Get a reference to the main module.
    PyObject* main_module =
        PyImport_AddModule("__main__");

    // Get the main module's dictionary
    // and make a copy of it.
    PyObject* main_dict =
        PyModule_GetDict(main_module);

    const char *script_source = "def main():\n\tprint('Hello'\n\nmain()";

    PyObject *res = PyRun_String(script_source,Py_file_input,main_dict,main_dict);
    if(res == NULL)
    {
        PyObject *ptype = NULL, *pvalue = NULL, *ptraceback = NULL;
        PyErr_Fetch(&ptype,&pvalue,&ptraceback);

        PyObject* py_filename = PyUnicode_FromString("filename");
        PyObject* file_name = PyObject_GetAttr(ptype,py_filename);

        PyObject* py_lineno = PyUnicode_FromString("lineno");
        PyObject* line_no = PyObject_GetAttr(ptype,py_lineno);
    }
}

我故意在 script_source 中插入了一个语法错误。

我无法从 file_name 和 line_no 对象中检索实际的文件名和行号。

我尝试调试 file_name 和 line_no 对象,内容如下所示。“语法错误对象的成员文件名”和“语法错误对象的成员行号”

这些对象是不可调用的,所以我不能在这些对象上使用 PyObject_Call() 变体。

有什么办法可以让我从这些对象的..中获取实际的文件名和行号?

在这个文件名中,我使用的是 PyRun_String()。

4

2 回答 2

3

我通过以下方式解决了它。我在 PyErr_Fetch() 之后使用了 PyErr_NormalizeException() 并且代码现在工作正常。

int main(int argc, char** argv)
{
    Py_Initialize();

    // Get a reference to the main module.
    PyObject* main_module =
        PyImport_AddModule("__main__");

    // Get the main module's dictionary
    // and make a copy of it.
    PyObject* main_dict =
        PyModule_GetDict(main_module);

    const char *script_source = "def main():\n\tprint('Hello'\n\nmain()";

    PyObject *res = PyRun_String(script_source,Py_file_input,main_dict,main_dict);
    if(res == NULL)
    {
        PyObject *ptype = NULL, *pvalue = NULL, *ptraceback = NULL;
        PyErr_Fetch(&ptype,&pvalue,&ptraceback);
        PyErr_NormalizeException(&ptype,&pvalue,&ptraceback);

        char *msg;
        char *file;
        int line;
        int offset;
        char *text;

        int res = PyArg_ParseTuple(pvalue,"s(siis)",&msg,&file,&line,&offset,&text);

        PyObject* file_name = PyObject_GetAttrString(pvalue,"filename");
        PyObject* file_name_str = PyObject_Str(file_name);
        PyObject* file_name_unicode = PyUnicode_AsEncodedString(file_name_str,"utf-8", "Error");
        char *actual_file_name = PyBytes_AsString(file_name_unicode);

        PyObject* line_no = PyObject_GetAttrString(pvalue,"lineno");
        PyObject* line_no_str = PyObject_Str(line_no);
        PyObject* line_no_unicode = PyUnicode_AsEncodedString(line_no_str,"utf-8", "Error");
        char *actual_line_no = PyBytes_AsString(line_no_unicode);

        printf("done");
    }
}
于 2013-05-29T05:57:09.560 回答
1

The attributes are set on the the PySyntaxErrorObject struct, but be aware that the struct is not exposed if you are adhering to Python's stable ABI. Otherwise you should be able to use a PyObject_GetAttr* function to get at the attributes.

于 2013-05-27T02:12:13.450 回答