异常
错误处理:
1、python错误处理机制:try...exception...finally...
若认为某些代码可能会出错时,就可以用try来运行这段代码,如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码即except语句块;执行完except后,如果有finally语句块,则执行finally语句块,至此,执行完毕
此外,如果没有错误发生,可以在except语句块后面加一个else,当没有错误发生时,会自动执行else语句
python的错误其实也是class,所有错误类型都继承自BaseException,所以在使用except时需要注意,它不但捕获该类型的错误,还把子类也‘一网打尽’
try: foo() except StandardError, e: print 'StandardError' except ValueError, e: print 'ValueError'
第二个except
永远也捕获不到ValueError
,因为ValueError
是StandardError
的子类,如果有,也被第一个except
给捕获了
BaseException +-- SystemExit +-- KeyboardInterrupt +-- GeneratorExit +-- Exception +-- StopIteration +-- StandardError | +-- BufferError | +-- ArithmeticError | | +-- FloatingPointError | | +-- OverflowError | | +-- ZeroDivisionError :除数为0,再用除法操作时,第二个参数为0时引发了该错误 | +-- AssertionError :断言失败,assert语句本身会抛出该错误 | +-- AttributeError :试图访问一个对象没有的属性,比如foo.x,但是foo没有属性x | +-- EnvironmentError | | +-- IOError :输入/输出异常(基本上是无法打开文件) | | +-- OSError | | +-- WindowsError (Windows) | | +-- VMSError (VMS) | +-- EOFError | +-- ImportError :无法引入模块或包,基本上是路径问题或名称错误 | +-- LookupError | | +-- IndexError :下标索引超出序列边界 | | +-- KeyError :试图访问不存在的键 | +-- MemoryError | +-- NameError :使用一个还未被赋予对象的变量 | | +-- UnboundLocalError :试图访问一个还未被设置的局部变量 | +-- ReferenceError | +-- RuntimeError | | +-- NotImplementedError | +-- SyntaxError :python代码非法,代码不能编译 | | +-- IndentationError :语法错误的子类,代码没有正确对齐 | | +-- TabError | +-- SystemError | +-- TypeError :传入对象类型与要求的不符合 | +-- ValueError :传入一个调用者不期望的值,即使值的类型是正确的 | +-- UnicodeError | +-- UnicodeDecodeError | +-- UnicodeEncodeError | +-- UnicodeTranslateError +-- Warning +-- DeprecationWarning +-- PendingDeprecationWarning +-- RuntimeWarning +-- SyntaxWarning +-- UserWarning +-- FutureWarning +-- ImportWarning +-- UnicodeWarning +-- BytesWarning
2、抛出错误
因为错误是class,捕获一个错误就是捕获到该class的一个实例。因此,错误并不是凭空产生的,而是有意创建并抛出的。python的内置函数会抛出很多类型的错误,我们编写的函数也可以抛出错误
如果要抛出错误,首先根据需求,可以定义一个错误的class,选择好继承关系,然后用 raise 语句抛出一个错误的实例:尽量使用python内置的错误类型
class FooError(StandardError):
pass
def foo(s):
n=int(s)
if n==0:
raise FooError('invalid value : %s' %s)
return 10/n
-------------------------------------------------------------------------------------------------------------------------------
调试:
1、用 print 把可能有问题的变量打印出来看看:坏处还得删除,运行结果会包含很多垃圾信息
def foo(s):
n=int(s)
print '>>> n=%d' % n
return 10/n
def main():
foo('0')
main()
输出:
>>> n=0
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in main
File "<stdin>", line 4, in foo
ZeroDivisionError: integer division or modulo by zero
2、断言:凡是用print来辅助的地方,都可以用断言(assert)来替代
def foo(s):
n=int(s)
assert n != 0,'n is zero!' assert语句后跟任何合法的python表达式,若表达式为True,则assert不做任何事情;若表达式为False,则会抛出AssertionError
return 10/n
def main():
foo('0')
main()
输出:
>>> main()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in main
File "<stdin>", line 3, in foo
AssertionError: n is zero!
3、logging好处,允许指定记录信息的级别,有debug、info、warning、error几个级别,当我们指定lenvel=INFO时,logging.debug就不起作用了