""" 异常处理 """ __author__on__ = 'shaozhiqi 2019/9/19' # 大量的代码来判断是否出错: # def foo(): # r = some_function() # if r == (-1): # return (-1) # # do something # return r # # # def bar(): # r = foo() # if r == (-1): # print('Error') # else: # pass # 用异常机制来处理 try: print('try...') r = 10 / 0 print('result:', r) except ZeroDivisionError as e: print('except:', e) # 执行结果: except: division by zero finally: print('finally...') print('END') # 我们认为某些代码可能会出错时,就可以用try来运行这段代码, # 如果执行出错,则后续代码不会继续执行,而是直接跳转至错误处理代码, # 即except语句块,执行完except后,如果有finally语句块,则执行finally语句块,至此,执行完毕。 # ----------------------------------------------------------------------------- # 如果没有错误发生,可以在except语句块后面加一个else,当没有错误发生时,会自动执行else语句: try: print('try...') r = 10 / int('2') print('result:', r) except ValueError as e: print('ValueError:', e) except ZeroDivisionError as e: print('ZeroDivisionError:', e) else: print('no error!') finally: print('finally...') print('END') # 执行结果: # try... # result: 5.0 # no error! # finally... # END # 异常列表:https://docs.python.org/3/library/exceptions.html#exception-hierarchy # ---------------------------------------------------------------- # 只要在最上层捕获了,就可以处理 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... # 不需要在每个可能出错的地方去捕获错误,只要在合适的层次去捕获错误就可以了 # ------------------------------------------------------------------------- # 如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了。 # 既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。 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') # --------------------------------------------------------------------- # 自定义异常,并抛出自定义异常,不捕获的话程序中断 class FooError(ValueError): pass def foo(s): n = int(s) if n == 0: raise FooError('invalid value: %s' % s) return 10 / n # foo('0') # __main__.FooError: invalid value: 0 # 抛出系统异常 def foo(s): n = int(s) if n == 0: raise ValueError('invalid value: %s' % s) return 10 / n def bar(): try: foo('0') except ValueError as e: print('ValueError!') raise bar() # ValueError: invalid value: 0 # 捕获错误目的只是记录一下,便于后续追踪。 # 由于当前函数不知道应该怎么处理该错误,所以,最恰当的方式是继续往上抛,让顶层调用者去处理。 # raise语句如果不带参数,就会把当前错误原样抛出。此外,在except中raise一个Error,还可以把一种类型的错误转化成另一种类型: try: 10 / 0 except ZeroDivisionError: raise ValueError('input error!') # 切勿在业务中如上处理,这样就不知道到底是啥异常了