在python中定义异常类层次结构的正确方法?

时间:2014-03-08 02:54:00

标签: python exception exception-handling

我希望能够像内置的那样引发异常,你可以随身携带一条消息,或者只是提升类名(隐式创建的实例)。像这样

raise IndexError

raise IndexError('Something went wrong, bro')

我的以下代码是否正确?

最初我在想这个:

class SomeError(Exception):
    def __init__(self, *args):
        if args:
            print ' '.join(args)

class SomeCriticalError(SomeError):
    def __init__(self, *args):
        super(SomeCriticalError,self).__init__(*args)
        print 'This is a critical error, process stopped ...'
        sys.exit(1)

class SomeCookiesError(SomeCriticalError):
    def __init__(self, *args):
        print 'Firefox cookies retrieving failed ..'   
        super(SomeCookiesError,self).__init__(*args)

但是在这种情况下,我必须为CmiCriticalError的每个子类定义__init__(),我觉得有些事情一定是错的(在每个子类中调用super()似乎很尴尬),然后我尝试了这个

class SomeError(Exception):
    def __init__(self, *args):
        if args:
            print ' '.join(args)
        else:
            print self

class SomeCriticalError(SomeError):
    def __init__(self, *args):
        super(SomeCriticalError,self).__init__(*args)
        print 'This is a critical error, process stopped ...'
        sys.exit(1)

class SomeCookiesError(SomeCriticalError):
    def __str__(self):
        return 'Firefox cookies retrieving failed ..'

但这仍然感觉很尴尬,我缺少什么?

基本上我想做的是处理异常实例本身的异常,比如sys.exit()中的SomeCriticalError,并且因为在我的主代码中,我可能会在多个地方引发SomeCookiesError ,我不想每次都传递相同的消息字符串参数,那么我可以做内置的异常吗? (当没有传递参数时,打印默认消息)

1 个答案:

答案 0 :(得分:0)

通常,Exception子类不负责处理导致它被引发的问题。这取决于错误处理代码(例如,围绕引发异常的地方的try / catch语句。异常类型应该限制自己呈现一个好消息,并封装任何适当的数据。

因此,在您的示例中,您应该仅仅通过不捕获它们来处理“关键”错误(或者在退出之前仅在最高级别捕获它们)。许多异常类都很简单:

class SomeCriticalError(Exception):
    pass

其他一些异常类可能会做得更多,但它们应该专注于记录情况的适当细节,而不是如何解决:

class CookieError(Exception):
    def __init__(self, cookie_name):
        super(CookiesError, self).__init__("Could not find Firefox cookie {!r}"
                                           .format(cookie_name)) # custom message

如果要调试CookieError,您需要一些额外的数据,您可以将异常类保存到self.data或其他任何内容(尽管您希望raise CookieError语法能够正常工作使__init__方法的所有参数都可选。)