2017-10-19 28 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

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