Python从哪里获取其回溯信息?

时间:2013-07-04 13:04:52

标签: python c debugging python-c-api

考虑以下verysimple.py

if '__main__' == __name__:
    prnt('Line1')

现在,如果我用> python verysimple.py执行它,我当然会受到以下问题的欢迎:

    Traceback (most recent call last):
        File "verysimple.py", line 2, in <module>
          prnt('Line1')
    NameError: name 'prnt' is not defined`

我想知道 Python中的哪些地方正在提取回溯信息(特别是错误的命令)。

我已经尝试在PyEval_FrameEx内找到自己的方式,但无法理解......

1 个答案:

答案 0 :(得分:1)

你走在正确的轨道上。解析代码树时,它只会多次运行PyEval_FrameEx。 最后,它将调用format_exc_check_arg()来格式化错误,对于我来说,这发生在Python版本3.3.2源代码的ceval.c的第2100行。 format_exc_check_arg()推断出令人反感的“对象”(prnt),并在PyErr_Format中调用errors.c来正确格式化异常字符串(异常类型及其对应的字符串,{{1} },已从此行2100传递给NAME_ERROR_MSG

我只使用此代码进行测试:

format_exc_check_arg()

然后通过我所拥有的Python的debug build运行它。

prnt('Line1') 中的周围代码是

PyEval_FrameEx

请注意,其上方的两行 TARGET(LOAD_NAME) w = GETITEM(names, oparg); if ((v = f->f_locals) == NULL) { PyErr_Format(PyExc_SystemError, "no locals when loading %R", w); why = WHY_EXCEPTION; break; } if (PyDict_CheckExact(v)) { x = PyDict_GetItem(v, w); Py_XINCREF(x); } else { x = PyObject_GetItem(v, w); if (x == NULL && PyErr_Occurred()) { if (!PyErr_ExceptionMatches( PyExc_KeyError)) break; PyErr_Clear(); } } if (x == NULL) { x = PyDict_GetItem(f->f_globals, w); Py_XINCREF(x); if (x == NULL) { if (PyDict_CheckExact(f->f_builtins)) { x = PyDict_GetItem(f->f_builtins, w); if (x == NULL) { // below is the line where the PyExc_NameError will be properly formatted. format_exc_check_arg( PyExc_NameError, NAME_ERROR_MSG, w); break; } Py_INCREF(x); } else { x = PyObject_GetItem(f->f_builtins, w); if (x == NULL) { if (PyErr_ExceptionMatches(PyExc_KeyError)) format_exc_check_arg( PyExc_NameError, NAME_ERROR_MSG, w); break; } } } } PUSH(x); DISPATCH(); 将是试图在内置语句中找到PyDict_GetItem(...)的行。函数(我从prnt推导出f->builtinsww本身来自上面代码中的第二个语句。 由于该字典查找失败,x == NULLNameError已设置并格式化。

希望这会对你有所帮助。