美文网首页
python raise的合理运用

python raise的合理运用

作者: 大兄弟 | 来源:发表于2019-06-24 18:24 被阅读0次

    捕获异常想必都不陌生,但是你真的捕获的恰当吗?对解决bug有帮助吗?还是说帮了倒忙?还是说加了几行无用的代码?

    exception 是流程控制, 用来代替没有 exception 机制语言的返回码机制。不是所有的异常都要抓取,应该只抓取你关心或当前 code 能处理的异常,其它的都向上丢。
    ------ by leader comment

    接下来看下几种异常捕获的方式:
    第一种:

    def exception():
        print 2 / 0
    
    if __name__ == "__main__":
        try:
            exception()
        except Exception:
            raise Exception("some_code failed!")
    

    抛出的异常:

    ➜  python python exception.py
    Traceback (most recent call last):
      File "exception.py", line 18, in <module>
        raise Exception("some_code failed!")
    Exception: some_code failed!
    

    从抛出的异常来看"some_code failed"不是我们想要的吧,最正确的提示应该是告诉我们分母不应该是0,
    而且这种方式会把some_code()的错误全部隐藏,看不到traceback和真正的错误是什么,无疑帮了倒忙,所以这种方式不可取。
    第二种:

    def exception():
        print 2 / 0
    
    def func1():
        exception()
    
    if __name__ == "__main__":
        try:
            func1()
        except Exception:
            import traceback
            traceback.print_exc()
    

    抛出的异常:

    ➜  python python exception.py
    Traceback (most recent call last):
      File "exception.py", line 17, in <module>
        func1()
      File "exception.py", line 12, in func1
        exception()
      File "exception.py", line 8, in exception
        print 2 / 0
    ZeroDivisionError: integer division or modulo by zero
    

    第二种方式比第一种方式好一丢丢,会把错误信息报出来,但是并没有输出到日志中,只是控制台打印输出,而且也没把错误向上抛出。
    第三种:

    def exception():
        print 2 / 0
    
    if __name__ == "__main__":
        try:
            exception()
        except Exception:
            raise
    

    抛出的异常:

    ➜  python python exception.py
    Traceback (most recent call last):
      File "exception.py", line 13, in <module>
        exception()
      File "exception.py", line 8, in exception
        print 2 / 0
    ZeroDivisionError: integer division or modulo by zero
    

    第三种方式好像终于获得了我们想要的错误,并且向上抛出了,但是有没有发现这种抛出的方式跟没try catch 一样。往下看:

    def exception():
        print 2 / 0
    
    if __name__ == "__main__":
        exception()
    

    抛出的异常:

    ➜  python python exception.py
    Traceback (most recent call last):
      File "exception.py", line 13, in <module>
        exception()
      File "exception.py", line 8, in exception
        print 2 / 0
    ZeroDivisionError: integer division or modulo by zero
    

    一样吧~ 那既然一样何必要加那几行try catch,所以第三种还是有瑕疵,
    看最后一种:

    class MyException(Exception):
        pass
    
    def exception():
        print 2 / 0
    
    if __name__ == "__main__":
        try:
            exception()
        except Exception:
            import sys
            exc_info = sys.exc_info()
            raise MyException('This is bug'), None, exc_info[2]
    

    抛出的异常:

    ➜  python python exception.py
    Traceback (most recent call last):
      File "exception.py", line 11, in <module>
        exception()
      File "exception.py", line 6, in exception
        print 2 / 0
    __main__.MyException: This is bug
    

    嗯,完美了!
    不仅抛出了自己定义的异常,本身的报错栈也一目了然!如果自定义的exception不恰当还可以看Traceback。

    每种语言都有捕获异常的方式,合理的运用事半功倍。不管用什么语言,在捕获异常的时候不要觉得自己定义的异常很完美,你以为的异常等真出错了不一定是你以为的,线上出了问题只看见个"This is bug",你什么心情?so 在捕获异常的时候尽量把自定义的和原本的报错也加上。

    本文参考:
    http://www.ianbicking.org/blog/2007/09/re-raising-exceptions.html
    http://xcodest.me/How_to_raise_python_exception.html

    相关文章

      网友评论

          本文标题:python raise的合理运用

          本文链接:https://www.haomeiwen.com/subject/dqjoqctx.html