自定义异常中的默认消息 - Python
Posted
技术标签:
【中文标题】自定义异常中的默认消息 - Python【英文标题】:Default message in custom exception - Python 【发布时间】:2018-08-19 20:32:15 【问题描述】:我想在 Python 中创建一个自定义异常,在没有任何参数的情况下引发该异常时,它将打印一条默认消息。
代码示例:
class CustomException(Exception):
pass # some code
raise CustomException()
并得到以下输出:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.CustomException: This is a default message!
【问题讨论】:
【参考方案1】:这是最简单的解决方案恕我直言,如何使用可以在需要时覆盖的默认消息定义自定义异常:
class CustomException(Exception):
def __init__(self, msg='My default message', *args, **kwargs):
super().__init__(msg, *args, **kwargs)
使用示例:
In [10]: raise CustomException
---------------------------------------------------------------------------
CustomException Traceback (most recent call last)
<ipython-input-10-259ae5202c8e> in <module>
----> 1 raise CustomException
CustomException: My default message
In [11]: raise CustomException()
---------------------------------------------------------------------------
CustomException Traceback (most recent call last)
<ipython-input-11-c1921a8781a6> in <module>
----> 1 raise CustomException()
CustomException: My default message
In [12]: raise CustomException('Foo bar')
---------------------------------------------------------------------------
CustomException Traceback (most recent call last)
<ipython-input-12-7efbf94f7432> in <module>
----> 1 raise CustomException('Foo bar')
CustomException: Foo bar
【讨论】:
我认为这实际上是最好的答案。 这很好用而且看起来很优雅。但是,我想指出,pylint 对此并不满意,并称其为无用的超级委托。 还有 pylint 报告关于keyword-arg-before-vararg【参考方案2】:下面的代码给出了解决方案:
class CustomException(Exception):
def __init__(self, *args, **kwargs):
default_message = 'This is a default message!'
# if any arguments are passed...
# If you inherit from the exception that takes message as a keyword
# maybe you will need to check kwargs here
if args:
# ... pass them to the super constructor
super().__init__(*args, **kwargs)
else: # else, the exception was raised without arguments ...
# ... pass the default message to the super constructor
super().__init__(default_message, **kwargs)
一个等效但更简洁的解决方案是:
class CustomException(Exception):
def __init__(self, *args, **kwargs):
default_message = 'This is a default message!'
# if no arguments are passed set the first positional argument
# to be the default message. To do that, we have to replace the
# 'args' tuple with another one, that will only contain the message.
# (we cannot do an assignment since tuples are immutable)
# If you inherit from the exception that takes message as a keyword
# maybe you will need to check kwargs here
if not args: args = (default_message,)
# Call super constructor
super().__init__(*args, **kwargs)
一个更简洁但受限制的解决方案是:
class CustomException(Exception):
def __init__(self):
default_message = 'This is a default message!'
super().__init__(default_message)
如果您只是将字符串文字传递给构造函数而不是使用default_message
变量,那么您当然可以在上述每个解决方案中保存一行。
如果您希望代码与 Python 2.7 兼容,则只需将 super()
替换为 super(CustomException, self)
。
正在运行:
>>> raise CustomException
将输出:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.CustomException: This is a default message!
并运行:
raise CustomException('This is a custom message!')
将输出:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
__main__.CustomException: This is a custom message!
这是前 2 个解决方案的代码将产生的输出。最后一个解决方案的不同之处在于至少使用一个参数来调用它,例如:
raise CustomException('This is a custom message!')
它会输出:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: __init__() takes 1 positional argument but 2 were given
因为它不允许在引发 CustomException 时将任何参数传递给它。
【讨论】:
【参考方案3】:在对this question 的回答中,这是声明自定义异常的好方法:
class MyException(Exception):
"""Docstring here"""
如果要定义许多异常,可以使用Exception
的子类作为它们的异常的超类,以使这些异常的文档字符串成为它们的默认消息:
class Doc_Default_Exception(Exception):
"""Subclass exceptions use docstring as default message"""
def __init__(self, msg=None, *args, **kwargs):
super().__init__(msg or self.__doc__, *args, **kwargs)
class MyException(Doc_Default_Exception):
"""Docstring here."""
raise MyException
输出:
Traceback (most recent call last):
File "C:\************************.py", line 9, in <module>
raise MyException
__main__.MyException: Docstring here
装饰器还可以使用自定义异常的文档字符串作为其默认消息:
import functools
def docstring_message(cls):
"""Decorates an exception to make its docstring its default message."""
# Must use cls_init name, not cls.__init__ itself, in closure to avoid recursion
cls_init = cls.__init__
@functools.wraps(cls.__init__)
def wrapped_init(self, msg=cls.__doc__, *args, **kwargs):
cls_init(self, msg, *args, **kwargs)
cls.__init__ = wrapped_init
return cls
@docstring_message
class MyException(Exception):
"""Docstring here"""
raise MyException
输出:
Traceback (most recent call last):
File "C:\************************.py", line 16, in <module>
raise MyException
__main__.MyException: Docstring here
当然,应该使用描述性消息引发异常,但有时默认回退就足够了,如果编写正确,文档字符串就足够了。
【讨论】:
以上是关于自定义异常中的默认消息 - Python的主要内容,如果未能解决你的问题,请参考以下文章