try...finally...
try...finally...语句用来表达这样的情况:在程序中,如果一个段代码必须要执行,即无论异常是否产生都要执行,那么此时就需要使用finally。 比如文件关闭,释放锁,把数据库连接返还给连接池等。
try: f = open("log.txt","r") a = 10 b = 0 ret = a / b
#捕获多个类型的异常 except IOError as ex: print(ex) except ZeroDivisionError as ex: print(ex) else: print("没有异常,真是happy!") finally: print("无论是否异常发生,都会执行!") |
import time try: f = open('log.txt') try: while True: content = f.readline() if len(content) == 0: break time.sleep(2) print(content) except KeyboardInterrupt: #如果在读取文件的过程中,产生了异常,那么就会捕获到 #比如按下了 ctrl+c print("捕获到了以外终止异常!") finally: f.close() print('关闭文件') except: print("没有这个文件") |
test.txt文件中每一行数据打印,但是我有意在每打印一行之前用time.sleep方法暂停2秒钟。这样做的原因是让程序运行得慢一些。在程序运行的时候,按Ctrl+c中断(取消)程序。
我们可以观察到KeyboardInterrupt异常被触发,程序退出。但是在程序退出之前,finally从句仍然被执行,把文件关闭。
try嵌套
import time try: f = open('log.txt') try: while True: content = f.readline() if len(content) == 0: break time.sleep(2) print(content) finally: f.close() print('关闭文件') except: print("没有这个文件") |
函数嵌套调用中:
def myDiv(a, b): return a / b
def test2(): a = 10 b = 0 try: ret = myDiv(a, b) except: print("test02已经捕获到了异常,但是不想处理!") #手动上抛异常 raise
def test3(): try: test2() except Exception as ex: print(ex)
#myDiv函数抛出异常 #test02没有处理,异常自动上抛 #test03接收到异常,并处理 #也就是说,异常是跨函数的 test3() |
总结:
- 如果try嵌套,那么如果里面的try没有捕获到这个异常,那么外面的try会接收到这个异常,然后进行处理,如果外边的try依然没有捕获到,那么再进行传递。
- 如果一个异常是在一个函数中产生的,例如函数A---->函数B---->函数C,而异常是在函数C中产生的,那么如果函数C中没有对这个异常进行处理,那么这个异常会传递到函数B中,如果函数B有异常处理那么就会按照函数B的处理方式进行执行;如果函数B也没有异常处理,那么这个异常会继续传递,以此类推。。。如果所有的函数都没有处理,那么此时就会进行异常的默认处理,即通常见到的那样。
- 注意观察上图中,当调用test3函数时,在test1函数内部产生了异常,此异常被传递到test3函数中完成了异常处理,而当异常处理完后,并没有返回到函数test1中进行执行,而是在函数test3中继续执行。
自定义异常抛出
你可以用raise语句来引发一个异常。异常/错误对象必须有一个名字,且它们应是Error或Exception类的子类。
下面是一个引发异常的例子:
#自定义异常类 class OutOfRangeException(Exception): def __init__(self,errMsg): self.msg = errMsg
def __str__(self): return self.msg
class Person(object): def __init__(self): self.name = None self.age = None
def setAge(self,age): if age < 0 or age > 100: raise OutOfRangeException("年龄应该在0-100之间!") self.age = age
def setName(self,name): self.name = name
def __str__(self): return "name:{} age:{}".format(self.name,self.age)
if __name__ == "__main__": person = Person() person.setName("Edward") person.setAge(80) print(person) try: person.setAge(101) except OutOfRangeException as ex: print(ex) |