Python:验证规则的用户定义异常
Python的文档中提到:
异常通常应该从Exception类派生,直接或间接地。
这里的“通常”让我有点困惑。
看看这段代码:
class good(Exception): pass
class bad(object): pass
Heaven = good()
Hell = bad()
>>> raise Heaven
Traceback (most recent call last):
File "<pyshell#163>", line 1, in <module>
raise Heaven
good
>>> raise Hell
Traceback (most recent call last):
File "<pyshell#171>", line 1, in <module>
raise Hell
TypeError: exceptions must be classes or instances, not bad
那么在阅读Python文档时,我是不是可以把“通常”理解为“总是”呢?
如果我有一个和Exception类没有关系的类层次结构,我想要“抛出”这个层次结构中的对象怎么办?
我可以随时用一个参数来抛出异常:
raise Exception, Hell
这让我觉得有点别扭。
那么,Exception(编辑:或者BaseException)类有什么特别之处,为什么只有它的“家族成员”可以被抛出呢?
5 个回答
通常情况下,使用“通常”这个词是因为有一些非常少见的异常类型不希望被普通的 Exception
处理器捕获。如果不确定的话,可以继承 Exception
,但这个规则也有例外。
大多数异常是用来表示某种错误或特殊情况,这些情况是由代码和数据引起的。这些异常都是 Exception
的子类。如果你想抛出自己的异常,它很可能也会属于这个类别,因此也应该继承 Exception
。如果你想要一个通用的异常处理器,比如用来记录错误,那么捕获 Exception
是完全合理的,这样可以通过这种方式捕获任何错误。
直接从 BaseException
继承的其他异常稍微有点不同。SystemExit
是在你调用 sys.exit()
时抛出的(或者你也可以直接抛出它)。如果你有一些顶层代码用来记录错误,那么你可能不希望它以相同的方式处理 SystemExit
。以前你必须为 SystemExit
包含一个单独的处理器,以防止普通的异常处理器捕获到这个情况。
KeyboardInterrupt
代表一种意外情况,但它是由用户的外部输入引发的,所以它可以在你代码的任何地方发生;它并不依赖于代码或数据。这意味着即使你想处理它,你也可能希望以不同于从 Exception
继承的异常的方式来处理它。
除了 Exception
之外,还有其他有效的类可以用来继承,比如 BaseException
。
你可以查看 异常层次结构 的文档了解更多信息。
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
etc..
在旧版本的 Python 中,可以抛出一些除了异常以外的东西。例如在 Python 2.5 中:
>>> raise "foo"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
foo
不过你会收到一个弃用警告:
DeprecationWarning: raising a string exception is deprecated
在新版本中,这种做法是不被允许的。你抛出的所有东西都必须是从 BaseException 继承而来的。
“所以在阅读Python文档时,我应该把'typically'换成''吗?”
不需要。
通常情况下,你应该从Exception这个类继承。就这么简单。这就是文档上说的。
有时候,你可能会从BaseException这个类继承。文档上没有提到这一点。你可能会选择扩展BaseException,因为你想要绕过except Exception
的处理。
那...有什么特别的呢?
它们是BaseException
的子类。你还需要知道什么呢?源代码是可以随时查看的。你可以阅读raise
语句的源代码,看看在抛出TypeError
之前,它具体检查了什么。
http://svn.python.org/view/python/trunk/Python/ceval.c?annotate=80817
查看第3456到3563行。
不过,从实际的角度来看,重要的就是“BaseException
的子类”。