Python学习笔记__8章错误、调试和测试__8.1章错误处理

# 这是学习廖雪峰老师python教程的学习笔记

1、概览

我们在运行程序或编写函数时,发生错误后,系统都会返回错误信息。我们可以通过某些机制,让错误信息更加明了

1.1、try

try机制的格式就是 try…except…finally。

try:   # try: 运行这段代码,若代码有误,就执行except

    print('try...')

    r = 10 / 0

    print('result:', r)

except ZeroDivisionError as e:  # except:捕获指定的错误类型并赋值给变量eexcept可以有多个

    print('except:', e)

finally:  # try except 执行完后,执行finally

    print('finally...')

注意:

Python的错误其实也是class,所有的错误类型都继承自BaseException,所以在使用except时需要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽”。比如:

try:
    foo()
except ValueError as e:
    print(
'ValueError')
except UnicodeError as e:
    print(
'UnicodeError')

第二个except永远也捕获不到UnicodeError,因为UnicodeErrorValueError的子类,如果有,也被第一个except给捕获了。

 

1.2、调用栈

$ python3 err.py

Traceback (most recent call last):

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

    main()

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

    bar('0')

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

    return foo(s) * 2

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

    return 10 / int(s)

ZeroDivisionError: division by zero

调用栈就是系统自己返回的错误信息。看调用栈,从上往下看。最后三行指明了错误的根源

1.3、记录错误

如果不捕获错误,可以让Python解释器来打印出错误堆栈,但程序也被结束了。

我们也可以捕获错误,把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。

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

import logging

def foo(s):

    return 10 / int(s)  # 错误根源

def bar(s):

    return foo(s) * 2

def main():

    try:

        bar('0')  # main()调用bar()bar()调用foo()

    except Exception as e:

        logging.exception(e)

 

main()

print('END')

 

因为有 logging.exception(e)。执行 .py文件后。会继续执行,打印出“END”

1.4、抛出错误

错误是class,捕获一个错误就是捕获到该class的一个实例。所以,错误并不是凭空产生的,而是有意创建并抛出的。抛出的错误既可以是Python的内置函数定义的,也可以是我们自己定义的

1、第一种抛出:

# err_raise.py

class FooError(ValueError):  # 定义了一个错误类

    pass

 

def foo(s):

    n = int(s)

    if n==0:

        raise FooError('invalid value: %s' % s)  # 抛出自己定义的错误类

    return 10 / n

 

foo('0') # 调用函数

2、第二种抛出:

# err_reraise.py

def foo(s):

    n = int(s)

    if n==0:

        raise ValueError('invalid value: %s' % s)  # 抛出ValueError错误

    return 10 / n

 

def bar():

    try:

        foo('0')

    except ValueError as e:  # 捕捉错误

        print('ValueError!')

        raise # raise不带参数,把当前错误原样抛出。因为调用了foo(),所以抛给foo()

 

bar() # 调用函数

ValueError!  # except捕获错误后的print

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   # foo()抛出捕获的错误

 

1.5、错误的转换

在except中raise一个Error,可以把一种类型的错误转化成另一种类型

try:

    10 / 0

except ZeroDivisionError:

    raise ValueError('input error!')


猜你喜欢

转载自blog.51cto.com/12758568/2116869