一、错误处理
高级语言都内置了一套“try…..except…..finally”错误处理机制。
①try机制
try:
r=12/0
print ('result:',r)
except ZeroDivisionEror,e: #e可用其他字符代替,表示一个变量,在这里e=='inter division or modulo by zero'
print 'except:',e
finally:#finnally可有可无,无论代码是否有错误都会执行
print 'finally....'
print 'end'
上面代码在计算12/0时会产生一个除法运算错误:
except: integer division or modulo by zero
finally….
end
当发生错误时不再执行print ‘result:’,r
若没有错误发生,except语句不会执行;另外错误会有不同种类,所以可以有多个不同的except语句;如果没有错误发生,可以在except语句后加一个else语句,没有错误发生就可以执行该语句。另:所有的错误类型都继承自BaseException,所以可以用一个expect StandardError,e: 语句,省去用多个except语句去捕获错误。
使用try….expect 可以跨越多层调用,调用函数,函数嵌套无论在哪一层出错都可以捕获到比如下例:
def foo(s)
return 10 / int(s)
def bar(s):
return foo(s) * 2
def main():
try:
bar('0')
except StandardError, e:
print 'Error!'
finally:
print 'finally...'
main()
输出:
Error integer division or modulo by zero
可见错误出现在foo()函数中,在函数调用中main()函数仍可以捕获到
②调用堆栈
如果错误为被找到,则会打印错误信息
def f1(s):
return 12/int(s)
def f2(s):
return f1(s)*2
def main():
f2('0')
main()
执行:结果如下
Traceback (most recent call last):
File "F:/python 代码/错误处理.py", line 7, in <module>
main()
File "F:/python 代码/错误处理.py", line 6, in main
f2('0')
File "F:/python 代码/错误处理.py", line 4, in f2
return f1(s)*2
File "F:/python 代码/错误处理.py", line 2, in f1
return 12/int(s)
ZeroDivisionError: integer division or modulo by zero
可以看出,出现错误的地方为:
File "F:/python 代码/错误处理.py", line 2, in f1
return 12/int(s)
③记录错误
python内置的logging模块可以记录错误,把错误堆栈打印出来,同时让程序继续执行下去。
import logging #先导入
def f1(s):
return 12/int(s)
def f2(s):
return f1(s)*2
def main():
try:
f2('0')
except StandardError,e: #增加的步骤
logging.exception(e)
main()
print('End')
于上个代码相比导入import,使用try…except。虽然同样出错,但打印完错误信息后会继续执行,并正常退出,执行代码如下:
ERROR:root:integer division or modulo by zero
Traceback (most recent call last):
File "F:/python 代码/错误处理.py", line 8, in main
f2('0')
File "F:/python 代码/错误处理.py", line 5, in f2
return f1(s)*2
File "F:/python 代码/错误处理.py", line 3, in f1
return 12/int(s)
ZeroDivisionError: integer division or modulo by zero
End
错误是一个class,例如python的内置函数:ValueError(),StandardError()…..或者我们自己定义一个错误类(必要的时候),但需要选择好继承关系例如:FooError(StandardError)…所以我们捕获到的错误就是类的一个实例。
我们可以根据需要,选择或定义一个错误类,用raise语句抛出错误。
def f3(s):
n=int(s)
if n==0:
raise StandardError('invalid value: %s' % s)
return 12/0
f3('0')
执行如下:
Traceback (most recent call last):
File "F:/python 代码/错误处理.py", line 21, in <module>
f3('0')
File "F:/python 代码/错误处理.py", line 19, in f3
raise StandardError('invalid value: %s' % s)
StandardError: invalid value: 0
打印完错误信息且程序继续执行。
另一种非常常见的错误处理方式:
def foo1(s):
n = int(s)
return 10 / n
def bar1(s):
try:
return foo1(s) * 2
except StandardError, e:
print 'Error!'
raise
def main1():
bar1('0')
main1()
执行结果如下:
Error!
Traceback (most recent call last):
File "F:/python 代码/错误处理.py", line 30, in <module>
main1()
File "F:/python 代码/错误处理.py", line 28, in main1
bar1('0')
File "F:/python 代码/错误处理.py", line 22, in bar1
return foo1(s) * 2
File "F:/python 代码/错误处理.py", line 19, in foo1
return 10 / n
ZeroDivisionError: integer division or modulo by zero
可见,编辑器已经知道了有错误,而且又把错误通过raise抛出便于管理者尽快找出错误原因!若无raise则只输出“Error”!
二、调试
logging
与assert判断或print打印错误相比,logging不会抛出错误
import logging
s='0'
n=int(s)
logging.info('n=%d' %n) #logging.info()可以输出一段文本,且其需放在可能会出错误的语句之前
print 10/n
运行后只会输出ZeroDivisionError,这跟logging制定记录的错误信息级别有关,有debug,info,warning,error等几个级别,例如在import logging后导入:
import logging
logging.basicConfig(level=logging.INFO)
会输出
INFO:root:n = 0
Traceback (most recent call last):
File "err.py", line 8, in <module>
print 10 / n
ZeroDivisionError: integer division or modulo by zero
指定不同的级别就会输出不同的信息
======================================
学艺不精、未完待续