2017-10-19 26 views
-1

我正在使用Python API for C/C++,并且我想在NameError的情况下检索 行号。Python C++ API:如何检索NameError的lineno属性

我跟着波纹管的问题中发现的说明:

How to retrieve filename and lineno attribute of SyntaxError

,我写了下面的代码:

PyObject *ptype = NULL, *pvalue = NULL, *ptraceback = NULL; 
PyObject *comp = NULL, *eval = NULL; 
char code[] = {"A=undef_var"}; 

comp = Py_CompileString(code, "", Py_file_input); 
if (comp) { 
    eval = PyEval_EvalCode(comp, PyEval_GetBuiltins(), NULL); 
} 
if (!comp || !eval) { 
    PyErr_PrintEx(1); // inside this function the PyErr_Fetch(ptype, pvalue, ptraceback) is called 

    // retrieve the information gained from PyErr_Fetch() called inside PyErr_PrintEx(1) 
    pvalue  = PySys_GetObject("last_value"); 
    ptype  = PySys_GetObject("last_type"); 
    ptraceback = PySys_GetObject("last_traceback"); 
    PyErr_NormalizeException(ptype, pvalue, ptraceback); 

    PyObject* line_no = PyObject_GetAttrString(pvalue,"lineno"); 
    if (line_no) { 
     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); 
    } 
} 

上面的代码返回正确的行号,以防python代码 包含一个SyntaxError(例如对于一个简单的Python代码,如“A =”), 但在NameError的情况下,行号未设置为相关适用于pvalue对象(例如对于Python代码:“A = undefined_var”)。

任何想法如何解决这个问题?

+0

你就不能使用boost库呢? 然后你可以看看这个stackoverflow链接: [如何获得Python异常文本](https://stackoverflow.com/questions/1418015/how-to-get-python-exception-text/37780954) – Spezi94

+0

不幸的是,我不能使用boost库。感谢你的回答! – tsahmatsis

+0

请注意,您必须单独检查**每个“Py_ *”函数**的**返回值,并相应地执行。 –

回答

0

随着@Antti哈帕拉的帮助下,并考虑张贴到这个question我总结以下解决方案解决方案:

PyObject *ptype = NULL, *pvalue = NULL, *ptraceback = NULL; 
PyObject *compile_obj = NULL, *eval_obj = NULL; 
PyObject *line_no = NULL, *line_no_str = NULL, *line_no_unicode = NULL; 
char *actual_line_no = NULL; 
char code[] = { "A=undef_var" }; 
int line_num = 0; 

compile_obj = Py_CompileString(code, "", Py_file_input); 
if (compile_obj) { 
    eval_obj = PyImport_ExecCodeModule((char *)"", compile_obj); 
} 
if (!compile_obj || !eval_obj) { 
    PyErr_PrintEx(1); // inside this function the PyErr_Fetch(ptype, pvalue, ptraceback) is called 
         // retrieve the information gained from PyErr_Fetch() called inside PyErr_PrintEx(1) 
    pvalue  = PySys_GetObject("last_value"); 
    ptype  = PySys_GetObject("last_type"); 
    ptraceback = PySys_GetObject("last_traceback"); 
    if (ptype) { 
     PyErr_NormalizeException(&ptype, &pvalue, &ptraceback); 
    } 
    if (compile_obj) { // NameError 
     if (ptraceback) { 
      PyTracebackObject *tb_o = (PyTracebackObject *)ptraceback; 
      line_num = tb_o->tb_lineno; 
     } 
    } else { //Syntax Error 
     line_no = PyObject_GetAttrString(pvalue, "lineno"); 
     if (line_no) { 
      line_no_str = PyObject_Str(line_no); 
      if (line_no_str)  line_no_unicode = PyUnicode_AsEncodedString(line_no_str, "utf-8", "Error"); 
      if (line_no_unicode) actual_line_no = PyBytes_AsString(line_no_unicode); 
      if (actual_line_no) line_num = atoi(actual_line_no); 

      Py_XDECREF(line_no); 
      Py_XDECREF(line_no_str); 
      Py_XDECREF(line_no_unicode); 
     } 
    } 
} 
Py_XDECREF(compile_obj); 
Py_XDECREF(eval_obj); 

return line_num; 
+0

您错过了*代码中至少有8次*返回值检查 - 此外,您还有几处泄漏。 –

+0

此外,你只是*假设*返回值。 –