Python 错误处理

发布时间:2019-08-21 07:49:47编辑:auto阅读(1334)

    1.1   错误处理

    1.1.1   try

    >>> try:

    ...    print('try...')

    ...    r = 10 / 0

    ...    print('result:', r)

    ... except ZeroDivisionError as e:

    ...    print('except:', e)

    ... finally:

    ...    print('finally...')

    ...    print('END')

    ...

    try...

    except: division by zero

    finally...

    END

    当我们认为某些代码可能会出错时,就可以用try来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码,即except语句块,执行完except后,如果有finally语句块,则执行finally语句块,至此,执行完毕。

    finally语句块无论是否执行except,都会被执行的

     

    同时定义多个except

    >>> try:

    ...    print('try...')

    ...    r = 10 / int('a')

    ...    print('result:', r)

    ... except ValueError as e:    --异常1

    ...    print('ValueError:', e)

    ... except ZeroDivisionError as e:   --异常2

    ...    print('except:', e)

    ... else:   --无异常时执行else

    ...    print('no error')

    ... finally:

    ...    print('finally...')

    ...    print('END')

    ...

    try...

    ValueError: invalid literal for int() withbase 10: 'a'

    finally...

    END

     

    跨越多层调用

    使用try...except捕获错误还有一个巨大的好处,就是可以跨越多层调用,比如函数main()调用foo()foo()调用bar(),结果bar()出错了,这时,只要main()捕获到了,就可以处理。

    >>> def foo(s):

    ...    return 10 / int(s)

    ...

    >>> def bar(s):

    ...    return foo(s) *2

    ...

    >>> def main():

    ...    try:

    ...        bar('0')

    ...    except Exception as e:

    ...        print('Error:', e)

    ...    finally:

    ...        print('finally...')

    ...

    >>> main()

    Error: division by zero

    finally...

    只要在合适的层次去捕获错误就可以了。

    1.1.2   调用堆栈

    [root@daidai python]# cat err.py

    #!/bin/bash/python

    # -*- coding:utf-8 -*-

     

    def foo(s):

       return 10 / int(s)

     

    def bar(s):

       return foo(s) * 2

     

    def main():

       bar('0')

     

    main()

     

    [root@daidai python]# python err.py

    Traceback (most recent call last):

     File "err.py", line 13, in <module>

       main()

     File "err.py", line 11, in main

       bar('0')

     File "err.py", line 8, in bar

       return foo(s) * 2

     File "err.py", line 5, in foo

       return 10 / int(s)

    ZeroDivisionError: division by zero    --最后便是错误的根源

    1.1.3   记录错误

    捕捉错误,把错误堆栈记录,让程序继续运行。

    Python内置的logging模块可以非常容易地记录错误信息。

    [root@daidai python]# cat err_logging.py

    #!/usr/bin/python

    # -*- coding:utf-8 -*-

     

    import logging

     

    def foo(s):

       return 10 / int(s)

     

    def bar(s):

       return foo(s) * 2

     

    def main():

       try:

           bar('0')

       except Exception as e:

           logging.exception(e)

     

    main()

    print('END')

    [root@daidai python]# python err_logging.py

    ERROR:root:division by zero

    Traceback (most recent call last):

     File "err_logging.py", line 14, in main

        bar('0')

     File "err_logging.py", line 10, in bar

       return foo(s) * 2

     File "err_logging.py", line 7, in foo

       return 10 / int(s)

    ZeroDivisionError: division by zero

    END

    1.1.4   抛出错误

    尽量使用python内置的错误类型

    错误是class,捕获一个错误就是捕获到该class的一个实例

    定义一个错误class,选择好继承关系。

    >>> class FooError(ValueError):

    ...    pass

    ...

    >>> def foo(s):

    ...    n = int(s)

    ...    if n == 0:

    ...         raise FooError('invalid value: %s' % s)

    ...    return 10 / n

    ...

    >>> foo('0')

    Traceback (most recent call last):

     File "<stdin>", line 1, in <module>

     File "<stdin>", line 4, in foo

    __main__.FooError: invalid value: 0     --自己定义的错误

     

    另一种错误处理方式——错误上抛

    >>> def foo(s):

    ...    n = int(s)

    ...    if n == 0:

    ...         raise ValueError('invalid value: %s' %s)    --python内置错误

    ...    return 10 /n

    ...

    >>> def bar():

    ...    try:

    ...        foo('0')

    ...    except ValueError as e:

    ...        print('ValueError')

    ...        raise    --raise语句如果不带参数,就会把当前错误原样抛出

    ...

    >>> bar()

    ValueError

    Traceback (most recent call last):

     File "<stdin>", line 1, in <module>

     File "<stdin>", line 3, in bar

     File "<stdin>", line 4, in foo

    ValueError: invalid value: 0

    其实这种错误处理方式不但没病,而且相当常见。捕获错误目的只是记录一下,便于后续追踪。但是,由于当前函数不知道应该怎么处理该错误,所以,最恰当的方式是继续往上抛,让顶层调用者去处理。好比一个员工处理不了一个问题时,就把问题抛给他的老板,如果他的老板也处理不了,就一直往上抛,最终会抛给CEO去处理。

     

    exceptraise一个Error,还可以把一种类型的错误转化成另一种类型

    >>> try:

    ...    10 / 0

    ... except ZeroDivisionError:

    ...    raise ValueError('input error')

    ...

    Traceback (most recent call last):

     File "<stdin>", line 2, in <module>

    ZeroDivisionError: division by zero

     

    During handling of the above exception,another exception occurred:

     

    Traceback (most recent call last):

     File "<stdin>", line 4, in <module>

    ValueError: input error


关键字