NameError 是一个内置类,因此您在 Python 中所做的任何事情都无法改变它的工作方式。
但是,Python 是开源的,因此您可以更改源代码来做您想做的事。您可以获取代码here。
来自Python source code,文件Python/ceval.c:(添加行号以便于查找):
83> #define NAME_ERROR_MSG \
84> "name '%.200s' is not defined"
这是一个包含该错误消息的 C 宏。在这个文件中后来使用了六次,显示了删除局部变量、删除全局变量、加载局部变量两次、加载全局变量两次的错误。
2315> format_exc_check_arg(tstate, PyExc_NameError,
2316> NAME_ERROR_MSG,
2317> name);
为了将消息更改为与上下文相关(匹配潜在变量名所必需的),您可以将此宏替换为分析当前范围、查找具有相似名称的变量并返回一个新的函数格式字符串,其中嵌入了变量名,例如"name '%.200s' is not defined. Did you mean 'the_variable'?"
或者,您可以让格式字符串接受两个子字符串,并向format_exc_check_arg 函数添加另一个参数,然后简单地添加对函数的调用,该函数只需要找到一个类似命名的变量作为最终参数。这将需要更改大约 10 个调用站点,包括之前的 6 个和一些相关异常的调用站点,但都以相同的方式进行,所以应该不会太难。
format_exc_check_arg 的代码是:
5400> static void
5401> format_exc_check_arg(PyThreadState *tstate, PyObject *exc,
5402> const char *format_str, PyObject *obj)
5403> {
5404> const char *obj_str;
5405>
5406> if (!obj)
5407> return;
5408>
5409> obj_str = PyUnicode_AsUTF8(obj);
5410> if (!obj_str)
5411> return;
5412>
5413> _PyErr_Format(tstate, exc, format_str, obj_str);
5414> }
这个可以改成
5400> static void
5401> format_exc_check_arg(PyThreadState *tstate, PyObject *exc,
5402> const char *format_str, PyObject *obj,
5403> PyObject* alt)
5404> {
5405> const char *obj_str;
5406> const char *alt_str;
5407>
5408> if (!obj)
5409> return;
5410>
5411> if (!alt)
5412> return;
5413>
5414> obj_str = PyUnicode_AsUTF8(obj);
5415> if (!obj_str)
5416> return;
5417>
5418> alt_str = PyUnicode_AsUTF8(alt);
5419> if (!alt_str)
5420> return;
5421>
5422> _PyErr_Format(tstate, exc, format_str, obj_str, alt_str);
5423> }
现在我们调用了_PyErr_Format,它现在还需要另一个参数。这是Python/errors.c:
952> PyObject *
953> _PyErr_Format(PyThreadState *tstate, PyObject *exception,
954> const char *format, ...)
955> {
956> va_list vargs;
957> #ifdef HAVE_STDARG_PROTOTYPES
958> va_start(vargs, format);
959> #else
960> va_start(vargs);
961> #endif
962> _PyErr_FormatV(tstate, exception, format, vargs);
963> va_end(vargs);
964> return NULL;
965> }
它已经接受了可变数量的参数,因此不需要更改。
编译修改后的代码,将其添加到您的路径中,您就拥有了带有自定义错误消息的 Python。
TL;DR:这只能通过修改 Python 本身的源代码来完成。