2017-10-19 9 views
-1

Python APIをC/C++に使用していて、NameErrorの場合には 行番号を取得したいと考えています。Python C++ API:NameErrorのlineno属性を取得する方法

Iが蛇腹質問内に見出される命令に続く:

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が含まれています(例: "A ="のような単純なPythonコードの場合)、 ですが、NameErrorの場合は行番号が設定されていませんpvalueオブジェクト(例: Pythonコードの場合: "A = undefined_var")。

どのようにすればこの問題を解決できますか?

+0

は、あなたがこのためだけにブーストライブラリを使用することができませんか? 次に、このスタックオーバーフローリンクをチェックアウトすることができます: [Python例外テキストの入手方法](https://stackoverflow.com/questions/1418015/how-to-get-python-exception-text/37780954) – Spezi94

+0

残念ながら、私はブーストライブラリを使用することはできません。答えをありがとう! – tsahmatsis

+0

**それぞれのPy_ *関数**の戻り値**を個別にチェックして、それに応じて**絶対にチェックしなければならないことに注意してください。 –

答えて

0

@Antti Haapalaの助けを借りて、私は以下のソリューションを締結し、この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

さらに、戻り値を*仮定しているだけです。 –

関連する問題