【问题标题】:How to Create Custom Error Messages in Python如何在 Python 中创建自定义错误消息
【发布时间】:2019-08-29 19:33:30
【问题描述】:

如何在 python 中创建自定义错误消息而不将每个语句包装在 try-except 子句中? 例如(假设python3.6),假设我在python提示符中输入以下代码:

the_variable=5
print(the_varible)

这将返回:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'the_varible' is not defined

假设我想返回一个自定义异常:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'the_varible' is not defined. Did you mean 'the_variable'?

当然,这是一个非常人为的例子,我可以轻松地将 这个特殊的 示例包装在 try: except 子句中(例如 herehere 和许多其他子句),但我更普遍的希望是自定义程序中所有语句的任何错误消息

例如,如果我创建一个名为 my_script.py 的文件,其中包含:

the_variable=5
print(the_varible)

我使用python my_script.py 运行它。我想收到与上面相同的自定义错误消息。

【问题讨论】:

  • 您可以将try/except 放在您的main() 函数中,然后它将捕获内部代码未专门捕获的任何错误。
  • @Barmar,我认为您正在做某事。您可以将其添加为答案,我可以接受吗?

标签: python error-handling customization


【解决方案1】:

您可以在 main() 函数中捕获所有错误,这通常是应用程序的启动函数。

def main():
    try:
        // all the rest of your code goes here
    except NameError as err:
        // your custom error handling goes here
    // other custom error handlers can go here

【讨论】:

    【解决方案2】:

    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 本身的源代码来完成。

    【讨论】:

      猜你喜欢
      • 2021-10-29
      • 2014-04-01
      • 1970-01-01
      • 2021-07-04
      • 2021-05-03
      • 1970-01-01
      • 1970-01-01
      • 2014-12-09
      • 2012-12-11
      相关资源
      最近更新 更多