Python:证明规则的用户定义的异常

时间:2010-05-08 10:59:15

标签: python exception

Python文档states

  

异常通常应该从Exception类派生,   直接或间接地。

'typically'这个词使我处于模棱两可的状态。

考虑代码:

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文档时,我应该用'typically'替换''吗?

如果我有一个与Exception类无关的类层次结构,并且我想“提升”属于该层次结构的对象,该怎么办?

我总是可以使用参数引发异常:

raise Exception, Hell

这对我来说似乎有些尴尬

Exception(EDIT:或BaseException)类有什么特别之处,只能提升其家庭成员?

5 个答案:

答案 0 :(得分:21)

除了Exception之外,您还可以继承其他有效的类,例如BaseException

请参阅exception hierarchy的文档。

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。

答案 1 :(得分:9)

  

“所以在阅读python文档时,   我应该用''改变'''吗?

没有

通常,您从Exception继承。期。这就是它所说的。

有时,您可能会继承BaseException。这就是它没有说的。您可以扩展BaseExcetion,因为您想要击败except Exception处理程序。

  

有什么特别的......

他们是BaseException的子类。你还需要知道什么?来源随时可用。您可以阅读raise语句的源代码,以便在它抛出TypeError之前确切地查看它所检查的内容。

http://svn.python.org/view/python/trunk/Python/ceval.c?annotate=80817

第3456至3563行。

然而,从实际角度来看,重要的是“BaseException的子类。”

答案 2 :(得分:3)

使用

'通常'是因为有一些非常罕见的异常类型不希望被通用Exception处理程序捕获。如果有疑问继承自Exception,但该规则有例外。

大多数异常用于指示由代码和数据导致的某种错误或异常情况。这些异常都是Exception的子类。如果你想提出自己的异常,它可能属于那个类别,因此也应该继承Exception。如果你想要一个通用异常处理程序,例如为了记录错误,捕获Exception并期望以这种方式捕获任何错误是完全合理的。

直接从BaseException继承的其他例外情况略有不同。当您致电SystemExit(或者您可以直接提出)时,会引发sys.exit()。如果您确实有一些记录错误的顶级代码,那么您可能不希望它以相同的方式处理SystemExit。您曾经必须为SystemExit包含一个单独的处理程序,以便阻止通用异常处理程序捕获该情况。

KeyboardInterrupt确实表示意外情况,但它是由用户的外部输入引发的,因此它可以在代码中的任何位置发生;它不以任何方式依赖于代码或数据。这意味着即使您确实想要处理它,您可能希望以不同于继承自Exception的异常来处理它。

答案 3 :(得分:0)

也可以引发从各种错误/异常类派生的东西,但这些东西通常是为其他东西保留的。

答案 4 :(得分:0)

有时你可能想要提出你不认为是例外的事情(但规则)。对于这些罕见的情况,人们可以认为raise除了例外之外还有其他的东西。

在一个递归计算中,在某个时刻找到答案,将它提升到向上等待的捕手可以非常整洁(而不是return这意味着递归必须预期这一点,向上传递它等等。)。

但是现在只有老式的类(出于兼容性原因我猜)和BaseException的派生可以引发,因为有太多的人滥用像字符串这样的异常。