Python学习笔记九 错误、调试

参考教程:廖雪峰官网https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000

一、错误处理

Python提供了一套try...except...finally...的错误处理机制,先看一个示例:

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语句;无论是否出错最后都会执行finally语句的代码。

这里因为出错的是除数是0这个错误,所以在except中直接写定了该中错误的类型“ZeroDivisionError”;但有时候我们不明确到底会错误类型,所以可以通过多个except去处理:

try:
    print("try...")
    r=10/int('a')
    print("result:",r)
except ValueError as e:  #处理值类型错误
    print("ValueError:",e)
except ZeroDivisionError as e:#处理除数为0错误
    print("except:",e)
finally:
    print("finally...")
print('END')

如果没有错误发生,我们也可以在try...except...后面跟一个else语句,这里的代码可以在没有错误发生时运行。

try:
    print("try...")
    r=10/int('11')
    print("result:",r)
except ValueError as e:  #处理值类型错误
    print("ValueError:",e)
except ZeroDivisionError as e:#处理除数为0错误
    print("except:",e)
else:
    print('no error!')
finally:
    print("finally...")
print('END')

使用try...except语句还有一个好处,就是跨越多层调用,假设有三个函数: foo() bar() main(),依此为调用关系,如果foo()运行时候出错了,我们在调用环节就可以对其进行处理。

def foo(s):
    return 10/int(s)

def bar(s):
    return foo(s)*2

def main():
    try:
        bar('0')
    except Exception as e:
        print("Exception:",e)
    finally:
        print('finally')

main()

#输出:
Exception: division by zero
finally

可以看出,我们不需要在每个可能出错的地方去捕获并处理错误,在合适的层次去处理就可以了。

 *调用栈

如果错误没有被捕获,就会一直往上一层抛出,如果一直没有被捕获处理,最后将被解释器捕获,并打印一个错误信息。

def foo(s):
    return 10/int(s)

def bar(s):
    return foo(s)*2

def main():
    bar('0')
    
main()

执行结果如下:

Traceback (most recent call last):  #错误追朔
  File "...", line 10, in <module>  #首先出错的是第10行的main()
    main()
  File "...", line 8, in main       #但上面出错的原因在第8行bar('0')
    bar('0')
  File "...", line 5, in bar        #但上面出错的原因在第5行return foo(s)*2
    return foo(s)*2
  File "...", line 2, in foo        #但上面出错的原因在第2行 return 10/int(s)
return 10/int(s)
ZeroDivisionError: division by zero  #这里已经不再追朔,而是已经找到错误源头,直接给出错误类型,是一个除数为0错误

上面的代码在出错后已经停止运行了,并且给出了追朔过程及错误信息。既然Python的traceback可以追朔出错原因,那它也提供了logging模块可以记录错误信息,同时即便出错也可以继续让程序运行下去。

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!")

二、调试

(一)断言(assert)

对于可能出错的地方都可以插入assert语句分析测试:

def foo(s):
    n=int(s)
    assert n!=0,'n is zero!'
    return 10/n

def main():
    foo('0')

main()

上述代码中增加了“assert n!=0,'n is zero!'”,表示:断言n必须不为0,否则报错信息。断言失败则会抛出AssertError:

Traceback (most recent call last):
。。。
AssertionError: n is zero!

(二)logging

和assert相比,logging不会抛出错误,而且可以输出错误信息到文本

import logging
logging.basicConfig(level=logging.INFO)

s='0'
n=int(s)
logging.info('n=%d',n)   #logging的用法同样是放到可能出错的代码处
print(10/n)

 

posted @ 2018-04-02 20:46  tsembrace  阅读(223)  评论(0编辑  收藏  举报