Python 异常处理try…except
今天一起来讲解下Python中异常处理(try…except)
1. 异常时什么
首先说一下何谓异常:
-
Python程序的语法是正确的;
-
但运行期检测到的错误被称为异常。
如:ZeroDivisionError,NameError,TypeError,PermissionError等等
下面是一个不同类型数据相加的异常错误的例子:
#!/usr/bin/python3
print('codes start')
a = 123 + 'abc'
print('codes end')
运行结果:执行第一句打印成功;执行a = 123 + 'abc’出现TypeError异常,程序中断。
Traceback (most recent call last):
Try codes start
File "D:/PythonCode/python_test1.py", line 96, in <module>
a = 123 + 'abc'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
所以Python出现了try…except的结构来处理异常,从而解决程序因为异常导致运行崩溃的问题
2. try语句规则
-
首先,执行try子句(在关键字try和关键字except之间的语句)
-
无异常发生,忽略except子句,try子句执行后结束。
-
try子句中发生异常,则try子句余下的部分将被忽略(不执行)。如果异常的类型和 except之后的名称相符,那么对应的except子句将被执行。
例子:
#!/usr/bin/python3
try:
print('do try start')
a = 123 + 'abc'
print('do try end')
except:
print("do except: ERROR")
运行结果:执行第一句打印成功;执行a = 123 + 'abc’出现TypeError异常;出现异常不再继续执行try剩余的子句;进入except字句。
do try start
do except: ERROR
- 如果某异常没有与任何的except匹配,那么这个异常将会传递给上层的try中。
例子:
#!/usr/bin/python3
print("Codes start")
try:
print('do try start')
a = 123 + 'abc'
print('do try end')
except NameError:
print("do except: ERROR")
print("Codes end")
运行结果:执行外层print成功;执行try第一子句打印成功;执行a = 123 + 'abc’出现TypeError异常;寻找TypeError的except没有找到;异常返回上层,上层没有处理异常,抛出异常,程序中中断。
Traceback (most recent call last):
Codes start
do try start
File "D:/PythonCode/python_test1.py", line 97, in <module>
a = 123 + 'abc'
TypeError: unsupported operand type(s) for +: 'int' and 'str'
- 一个 try 语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。(有点像C语言中的switch case结构)
例子:
print("Codes start")
try:
print('do try start')
a = 123 + 'abc'
print('do try end')
except NameError:
print("do except: NameError")
except TypeError:
print("do except: TypeError")
print("Codes end")
运行结果:执行except TypeError子句
Codes start
do try start
do except: TypeError
Codes end
-
处理程序将只针对对应的try子句中的异常进行处理,而不是其他的 try 的处理程序中的异常。
-
一个except子句可以同时处理多个异常,这些异常将被放在一个括号里成为一个元组。
例子:
#!/usr/bin/python3
print('Codes start')
try:
print('do try start')
a = 123 + 'abc'
print('do try end')
except (NameError, TypeError):
print("do except: Error")
print('Codes end')
运行结果:
Codes start
do try start
do except: Error
Codes end
- 最后一个except(不带异常参数)子句可以忽略异常的名称,它将被当作通配符使用(如同C语言中的switch case结构中的default)。
例子:
#!/usr/bin/python3
print('Codes start')
try:
print('do try start')
a = 123 + 'abc'
print('do try end')
except NameError:
print("do except: NameError")
except PermissionError:
print("do except: PermissionError")
except:
print("do except: Errot")
print('Codes end')
运行结果:
Codes start
do try start
do except: Error
Codes end
- try except 语句还有一个可选的else子句,如果使用这个子句,那么必须放在所有的except子句之后。这个子句将在try子句没有发生任何异常的时候执行。
例子:
#!/usr/bin/python3
print('Codes start')
try:
print('do try start')
a = 123 + 456
print('do try end')
except:
print("do except: Error")
else:
print('Codes end')
运行结果:
Codes start
do try start
do try end
Codes end
- 异常处理并不仅仅处理那些直接发生在try子句中的异常,而且还能处理子句中调用的函数(甚至间接调用的函数)里抛出的异常
#!/usr/bin/python3
def sum_function():
a = 123 + 'abc'
print('Codes start')
try:
print('do try start')
sum_function()
print('do try end')
except:
print("do except: Error")
else:
print('Codes end')
运行结果:
Codes start
do try start
do except: Error
3. 抛出异常
Python 使用 raise 语句抛出一个指定的异常。
raise 唯一的一个参数指定了要被抛出的异常。它必须是一个异常的实例或者是异常的类(也就是 Exception 的子类)。
#!/usr/bin/python3
print('Codes start')
try:
raise NameError("ssssss")
except:
print("do except: Error")
raise
4. 用户自定义异常
可以通过创建一个新的异常类来拥有自己的异常。异常类继承自 Exception 类,可以直接继承,或者间接继承,例如:
>>>class MyError(Exception):
def __init__(self, value):
self.value = value
def __str__(self):
return repr(self.value)
>>> try:
raise MyError(2*2)
except MyError as e:
print('My exception occurred, value:', e.value)
My exception occurred, value: 4
>>> raise MyError('oops!')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
__main__.MyError: 'oops!'
5. 定义清理行为:finally
try 语句还有另外一个可选的子句,它定义了无论在任何情况下都会执行的清理行为。 例如:
#!/usr/bin/python3
print('Codes start')
try:
a = 123 + 'abc'
except:
print("do except: Error")
finally:
print("do finally")
Codes start
do except: Error
do finally
如果一个异常在 try 子句里(或者在 except 和 else 子句里)被抛出,而又没有任何的 except 把它截住,那么这个异常会在 finally 子句执行后被抛出。