我正在使用C / C ++的python API,我想检索它 NameError的行号。
我按照下面问题中的说明进行操作:
How to retrieve filename and lineno attribute of SyntaxError
我写了以下代码:
Private Function getcursor() As Cursor
If Date.Now.Month <> 10 Then Return Cursors.WaitCursor
If Date.Now.Day < 15 Then Return Cursors.WaitCursor
Dim rnd As New Random()
Select Case rnd.Next(0, 2)
Case 0
'Return New Cursor(New IO.MemoryStream(My.Resources.pumpkin))
Return New Cursor(New IO.MemoryStream(My.Resources.pumpkin))
Case 1
Return New Cursor(New IO.MemoryStream(My.Resources.pumpkin2))
Case 2
Return New Cursor(New IO.MemoryStream(My.Resources.pumpkin3))
Case Else
Return Cursors.WaitCursor
End Select
End Function
上面的代码返回正确的行号,以防python代码 包含一个SyntaxError(例如,对于像“A =”这样的简单python代码), 但是在NameError的情况下,行号没有正确设置到pvalue对象(例如对于python代码:“A = undefined_var”)。
任何想法如何解决这个问题?
答案 0 :(得分: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;