异常就是程序运行错误或者逻辑混乱。需要给客户友好的提示。异常一般是程序中无法完全避免,一般通过一定的手段,尽量减少异常的发生。
看如下示例:
print('*'*10)
open('1.txt','r')
print('try..........')
print('except......')
print('end........')
结果如下:

系统会报错,因为打开了一个不存在文件,错误提示FileNotFoundError。当python检测到一个错误时,解释器就无法继续执行了,反而出现了一些错误提示,这就是所谓的异常。可以使用try except来捕获异常。看如下代码:
print('*'*10)
try:
open('1.txt','r')
print('try..........')
except Exception:
print('except......')
print('end........')

此程序看不到任何错误,因为用except捕获到了Exception异常,并添加了异常处理的办法。也就是说将可能产生异常的代码放在try里面,在except里面写入处理异常的代码。
如果代码存在多个异常时,将如何解决?观察如下代码:
print('begin.......')
try:
open('1.txt','r')
num2 = 10/0
print('error2.........')
except FileNotFoundError:
print('*'*20)
print('over........')
结果如下:

因为已经遇到了文件不存在的异常,所以直接进行异常处理,跳过了10/0.如果之前没有异常,程序是否可以正常捕获异常呢?
print('begin.......')
try:
open('1.txt','w')
print('$'*20)
num2 = 10/0
print('error.........')
except FileNotFoundError:
print('*'*20)
print('over........')
结果如下:

此时发现系统报错,原因是捕获到的异常是ZeroDivisionError而不是FileNotFoundError ,系统无法做错相应的异常处理。那就需要为异常捕获添加多个异常类型。代码如下:
print('begin.......')
try:
open('1.txt','w')
print('$'*20)
num2 = 10/0
print('error.........')
except (FileNotFoundError,ZeroDivisionError):
print('*'*20)
print('over........')
结果如下:

为异常添加了多个类型后,代码又可以正常运行了。如何获得异常信息,看如下代码:
print('begin.......')
try:
open('1.txt','w')
print('$'*20)
num2 = 10/0
print('error.........')
except (FileNotFoundError,ZeroDivisionError) as ret:
print('*'*20)
print(ret)
print('over........')
存储异常信息,结果如下:

同样可以用Exception代替元组。同时可以添加else。
try:
print('......1......')
f=open('1.txt','r')
print('......2.......')
except Exception:
print('处理异常。。。。')
else:
print('没有异常。。。。')
结果如下:

try:
print('......1......')
f=open('1.txt','r')
num = 10/0
f.close()
print('......2.......')
except Exception:
print('处理异常。。。。')
else:
print('没有异常。。。。')
结果如下:

如上代码,打开文件后又出现了其他错误,去处理异常,导致无法关闭打开的文件,导致资源的浪费。如何解决这个问题,看如下代码:
try:
print('......1......')
f=open('1.txt','r')
num = 10/0
f.close()
print('......2.......')
except:
print('处理异常。。。。')
print(f.closed)
结果如下:

try:
print('......1......')
f=open('1.txt','r')
num = 10/0
print('......2.......')
except:
print('处理异常。。。。')
finally:
f.close()
print(f.closed)
结果如下:

异常的传递
try嵌套:
try:
print('...1-1...')
try:
print('...2-1...')
num = 10/0
print('...2-2...')
except FileNotFoundError:
print('except2......')
except:
print('except1......')
结果如下:

函数的嵌套调用:
def test1():
print('...1-1...')
print(num)
print('...1-2...')
def test2():
print('...2-1...')
test1()
print('...2-2...')
def test3():
print('...3-1...')
try:
test1()
print('...3-2...')
except:
print('有异常。。。')
print('...3-3...')
#test1()
#test2()
test3()
分别调用test1()和test2()都会报出NameError的错误。调用test3()的结果是:

抛出异常
'''
raise抛出异常
'''
def f1():
print('f1.....begin........')
num = 1/0
print('f1.....end..........')
def f2():
print('f2.....begin........')
f1()
print('f2.....end..........')
def f3():
print('f3.....begin........')
try:
f2()
except Exception as ex:
print(ex)
raise
print('f3.....end..........')
try:
f3()
except Exception as ret:
print('解决异常。。。')
print(ret)
结果如下:

自定义异常
'''
raise自定义异常
'''
class SexException(Exception):
def __init__(self,msg):
self.msg = msg
def f():
message = input('请输入性别:')
if message !='男' and message !='女':
raise SexException('你输入的是%s。请输入‘男’或‘女’,其他无效'%message)
try:
f()
except SexException as ret:
print(ret)
结果如下:

如果try嵌套,那么如果里面的try没有捕获到这个异常,那么外面的try会接收到这个异常,然后进行处理,如果外边的try依然没有捕获到,那么再进行传递。。。
如果一个异常是在一个函数中产生的,例如函数A---->函数B---->函数C,而异常是在函数C中产生的,那么如果函数C中没有对这个异常进行处理,那么这个异常会传递到函数B中,如果函数B有异常处理那么就会按照函数B的处理方式进行执行;如果函数B也没有异常处理,那么这个异常会继续传递,以此类推。。。如果所有的函数都没有处理,那么此时就会进行异常的默认处理,即通常见到的那样。