【问题标题】:How to customize exception message如何自定义异常消息
【发布时间】:2016-11-17 06:50:26
【问题描述】:
# python 3.5
>>> class MyError(Exception):
...   pass
...
>>> raise MyError('message')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
__main__.MyError: message

我希望仅打印 message 而不是 __main__.MyError: message 的异常。我尝试在MyError 本身及其元类中定义__str____repr__,但这些都没有效果。 python解释器从哪里得到__main__.MyError

请注意,我可以轻松更改 MyError 实例的打印方式,以及 MyError 本身的打印方式,但对异常消息都没有任何影响:

class MyType(type):
  def __str__(self):
    return '***'

class MyError(Exception, metaclass=MyType):
  def __str__(self):
    return 'xxx'

print(MyError) # ***
print(MyError()) # xxx
raise MyError() # still the same

【问题讨论】:

  • 您不想捕获并打印消息?
  • __main__.MyError 是您提出的异常对象。
  • @AChampion 当然可以,但我通常可以自定义对象的字符串表示。在这种情况下并非如此。
  • @yBot 当然可以,但我正在尝试了解异常报告的工作原理。
  • 您可以自定义__str__()__repr__(),但如果您想自定义解释器如何打印未处理的异常,则需要重新定义sys.excepthook()。你当然可以处理它。

标签: python python-3.x


【解决方案1】:

我能得到的最接近的是:

In [6]: raise MyError("some message")
---------------------------------------------------------------------------
MyError                                   Traceback (most recent call last)
<ipython-input-2-4bd48c5b1ce0> in <module>()
----> 1 raise MyError("some error message")

MyError: some error message

有一种方法可以删除类名前面的前导 __main__. 文本。甚至还有一种方法可以删除类名本身,所以输出如下所示:

In [6]: raise MyError("some error message")
---------------------------------------------------------------------------
                                          Traceback (most recent call last)
<ipython-input-6-4bd48c5b1ce0> in <module>()
----> 1 raise MyError("some error message")

: some error message

但是,我找不到删除 : 符号的方法。我的猜测是,这个符号是由解释器生成的,以便清楚地将异常输出与其他输出类型分开。

这是我使用的解决方案:

class MyError(Exception):
    __module__ = None
    def __init__(self, *args, **kwargs):
        Exception.__init__(self, *args, **kwargs)
        self.__class__.__name__ = "CustomTextHere"

还有一些输出:

In [8]: MyError
Out[8]: MyError

In [9]: MyError()
Out[9]: None.CustomTextHere()

In [11]: raise MyError()
---------------------------------------------------------------------------
CustomTextHere                            Traceback (most recent call last)
<ipython-input-11-f389ee70e588> in <module>()
----> 1 raise MyError()

CustomTextHere: 

In [12]: raise MyError("some error message")
---------------------------------------------------------------------------
CustomTextHere                            Traceback (most recent call last)
<ipython-input-12-4bd48c5b1ce0> in <module>()
----> 1 raise MyError("some error message")

CustomTextHere: some error message

如果您只想获得: 符号,您可以使用:

self.__class__.__name__ = ""

【讨论】:

    【解决方案2】:

    该行的第一部分,在冒号之前,是引发异常的类型。它与返回的格式相同:

    >>> class MyError(Exception):
    ...     pass
    ...
    >>> print(type(MyError("message")))
    <class '__main__.MyError'>
    

    通常,您的自定义异常类将放在某个文件(例如 file.py)中并导入,因此在这种情况下,它将是 file.MyError 而不是 __main__.MyError。但是,由于您当前使用的是在主 python 文件中定义的异常,它必须使用的唯一命名空间是 __main__

    长话短说,如果你想让它更漂亮,把它放在另一个文件中,用你喜欢的名字命名。

    【讨论】:

    • &lt;class '__main__.MyError'&gt;MyError 类的字符串表示形式。我可以通过在MyError 的元类中定义__str__ 轻松自定义它。但正如我所说,我无法更改 python 异常报告显示的内容。另请注意,__main__.MyError&lt;class '__main__.MyError'&gt;相同。
    • 所以我在 Python 源代码中做了一些挖掘,看来字符串的确定方式是 .;您可以通过重命名类或动态修改 MyError.__name__ 轻松更改类名。但是,我不相信有一种方法可以动态更改模块名称,因为这是在 C 源代码(评论末尾的链接)中根据正在执行的文件确定的。不过,我并不完全清楚这是如何工作的,所以这是可能的。 github.com/python/cpython/blob/master/Python/pythonrun.c#L756
    • 是的,你是对的。您可以将此添加到您的答案中吗?
    • 我想我会忽略它,因为其他答案似乎可以更好地解决问题!我基本上说我不知道​​这是否可以做到,他们证明了它可以。
    猜你喜欢
    • 2015-11-04
    • 2012-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多