0

考虑以下内容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,但就是想不通……

4

1 回答 1

1

你走在正确的轨道上。解析代码树时,它只是运行PyEval_FrameEx多次。最后,它将调用format_exc_check_arg()格式化错误,对我来说,这发生在ceval.cPython 3.3.2 版源代码的第 2100 行。 format_exc_check_arg()推断出令人反感的prnt“对象” (PyErr_Formaterrors.cNAME_ERROR_MSGformat_exc_check_arg()

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

prnt('Line1')

然后通过我周围的 Python 3.3调试版本运行它。

周围的代码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在内置语句和函数中查找的行(我推断出 from应用f->builtins到的,它本身是从上面代码中的第二个语句中获得的。由于该字典查找将失败,并且已设置并格式化。wwx == NULLNameError

希望这可以进一步帮助您。

于 2013-07-05T12:02:35.700 回答