20210225-1 Python错误与异常
作者:互联网
一、什么是异常
Python错误与异常
什么是异常
> 异常是一个事件,该事件会在程序执行过程中发生,影响程序的正常执行。一般情况下,在Python无法正常处理程序时就会发生异常。异常是Python的对象,表示一个错误。当Python脚本发生异常时,我们需要捕获并处理异常,否则程序会终止执行。
> 每一个异常都是一些类的实例,这些实例可以被引用,并且可以用很多种方法进行捕捉,使得错误可以被处理,而不是让整个程序失败。
代码里会有很多异常,比如 NameError 名称错误,Syntax Error 语法异常,Type Error 类型错误,Value Error值异常;这四种都是异常,异常其实是一个事件
代码里有异常是非常正常的事情,捕获到异常,扔掉就可以了
>>> 10*(1/0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ZeroDivisionError: division by zero
>>> 4+a1*3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'a1' is not defined
>>> '2'+2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can only concatenate str (not "int") to str
这些就叫做异常
二、异常处理
异常处理
> try语句的基本形式为try/except。try/except语句用来检测try语句块中的错误,从而让except语句捕获异常信息并处理。如果你不想在发生异常时结束程序,只需在try语句块中捕获异常即可。
> 捕获异常的语法如下:
> 异常捕捉try/except
1-1def exp_exception(x,y):try: a=x/yprint('a=',a)return aexcept Exception:print("程序出现异常,异常信息:被除数为0") exp_exception(2,2)=>a= 1.0
1-2def exp_exception(x,y):try: a=x/yprint('a=',a)return aexcept Exception:print("程序出现异常,异常信息:被除数为0") exp_exception(2,0)=>程序出现异常,异常信息:被除数为0
> 捕捉多个异常
1-1def exp_exception(x,y):try: a=x/y b=nameprint('a=',a)return aexcept ZeroDivisionError:print("除数不能为0")except NameError:print("没有你要找的名字") exp_exception(2,0)=>除数不能为0
1-2def exp_exception(x,y):try: a=x/y b=nameprint('a=',a)return aexcept ZeroDivisionError:print("除数不能为0")except NameError:print("没有你要找的名字") exp_exception(2,2)=>没有你要找的名字
> 使用一个块捕捉多个异常
> 如果需要使用一个块捕捉多个类型异常,可以将它们作为元组列出。使用该方式时,遇到的异常类型是元组中的任意一个,都会走异常流程。
> 这么做有什么好处呢?假如我们希望多个except子句输出同样的信息,就没有必要在几个except子句中重复输入语句,放到一个异常块中即可。
刚刚使用 except 捕获了两个异常,现在想把两个异常写到一个except中
def exp_exception(x,y):try: a=x/y b=nameprint('a=',a)return aexcept (ZeroDivisionError,NameError,TypeError):print("你的输出数据有误!") exp_exception(2,'0')=>你的输出数据有误!
异常处理
> 捕捉对象
> 如果希望在except子句中访问异常对象本身,也就是看到一个异常对象真正的异常信息,而不是输出自己定义的异常信息,可以使用as e的形式,我们称之为捕捉对象。
def exp_exception(x,y):try: a=x/y b=nameprint('a=',a)return aexcept (ZeroDivisionError,NameError,TypeError) as e:print(e) # 输出 e,这地方不要写自己自定义的内容 exp_exception(2,'0') exp_exception(2,0) exp_exception(2,2)=>unsupported operand type(s) for /: 'int' and 'str'division by zero name 'name' is not defined
这就是捕捉对象,前面的异常提示是自定义的,捕捉对象的意思是系统给的系统提示,用 as e 即可
用系统给出的提示相比更便于定位
> 全捕捉
> 在实际编码过程中,即使程序能处理好几种类型的异常,但有一些异常还是会从我们手掌中溜走。对于这种情况我们根本无法预测会发生什么,也无法提前做任何准备。在这种情况下,与其使用不是捕捉异常的try/except语句隐藏异常,不如让程序立即崩溃。
def exp_exception(x,y):try: a=x/y b=nameexcept (ZeroDivisionError,NameError,TypeError) as e:print(e) exp_exception(2,'')=>unsupported operand type(s) for /: 'int' and 'str'
这样b=name的异常就逃走了,没有对 b 进行检查
对于这种情况,无法预测未来会发生什么,也没办法提前做任何准备,所以缺陷一定会产生,所以这时不如让异常直接崩溃,直接在后面什么都不写就可以了
def exp_exception(x,y):try: a=x/y b=nameexcept:print("Error") exp_exception(2,'')=>Error
后面什么都不写就叫全捕捉,当然这只是一种解决方案,从实用性角度看不建议这样做,因为这样捕捉异常非常危险,会隐藏所有没有预先想到的错误
> try/except...else
> try/except 语句还有一个可选的 else 子句,如果使用这个子句,那么必须放在所有的 except 子句之后。
> else 子句将在 try 子句没有发生任何异常的时候执行。
> try/except...else
def exp_exception(x,y):try: a=x/yexcept:print("Error") else:print("程序没有错误,执行结束") exp_exception(2,'') exp_exception(2,2)=>Error
程序没有错误,执行结束
当程序没有异常时,会执行 else 子句流程
> try-finally 语句
> try-finally 语句无论是否发生异常都将执行最后的代码。
> 在有finally的异常处理程序中,finally中的子句一定是最后执行的。finally子句在关闭文件或数据库连接时非常有用
如果有异常,try => except => finally
如果无异常,try => else => finally
def use_finally(x,y):try: a=x/yfinally:print("不管有没有异常,都会执行我的哦~") use_finally(2,2) use_finally(2,0)=>不管有没有异常,都会执行我的哦~不管有没有异常,都会执行我的哦~Traceback (most recent call last): File "d:/VSCode/Untitled-1.py", line 10, in <module> use_finally(2,0) File "d:/VSCode/Untitled-1.py", line 5, in use_finally a=x/y ZeroDivisionError: division by zero
但这引起了一个新的问题,虽然执行了 finally 语句,但是还是抛出异常了
能不能用 except 在 try 里面解惑它呢
def use_finally(x,y):try: a=x/yexcept ZeroDivisionError:print("除数不能为0")finally:print("不管有没有异常,都会执行我的哦~") use_finally(2,2) use_finally(2,0)=>不管有没有异常,都会执行我的哦~除数不能为0 不管有没有异常,都会执行我的哦~
现在加上else也是一样可以的
def use_finally(x,y):try: a=x/yexcept ZeroDivisionError:print("除数不能为0")else:print("程序执行成功")finally:print("不管有没有异常,都会执行我的哦~") use_finally(2,2) use_finally(2,0)=>程序执行成功 不管有没有异常,都会执行我的哦~除数不能为0 不管有没有异常,都会执行我的哦~
除了 try,后面的 except else 和 finally 都被称为 try 的子句,必须和 try 配合使用才有意义
三、抛出异常
抛出异常
> Python 使用 raise 语句抛出一个指定的异常。
> raise语法格式如下:
前面一直在说捕获异常,异常必须是能够抛出来才能捕获的,python中使用 raise 抛出指定的异常
使用 raise 触发异常,把异常引出来即可,用实例调用 raise 语句,引发异常
>>> raise Exception
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Exception
>>> raise NameError("This is NameError")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: This is NameError
通过 这两个实例,可以看出,第一个实例引发没有相关错误信息的普通异常
第二个输出了一些错误提示;
如果只想知道有没有抛出异常,并不想处理它,使用一个 raise 就可以把异常抛出
try:raise NameError("这是一个NameError")except NameError:print("捕捉到NameError") # 不加 raise,输出对应字符就结束=>捕捉到NameError
try:raise NameError("这是一个NameError")except NameError:print("捕捉到NameError")raise=>捕捉到NameError Traceback (most recent call last): File "d:/VSCode/Untitled-1.py", line 4, in <module> raise NameError("这是一个NameError") NameError: 这是一个NameError
这样又把 NameError异常抛出来了,raise可以抛出更深更详尽的异常信息
Python重要的内建异常类
Exception:常规错误的基类
AttributeError:对象没有这个属性
IOError:输入/输出操作失败
IndexError:序列中没有此索引
KeyError:映射中没有这个键
NameError:未声明/初始化对象(没有属性)
SyntaxError:python语法错误
SystemError:一般解释器系统错误
ValueError:传入无效的参数
标签:NameError,exception,错误,Python,try,finally,20210225,exp,异常 来源: https://blog.51cto.com/15149862/2690586