一.什么是异常
1.错误
在运行或编写一个程序时常会遇到错误异常,这时 python 会给你一个错误提示类名,告诉出现了什么样的问题(Python是面向对象语言,所以程序抛出的异常也是类)。能很好的理解这些错误提示类名所代表的意思,可以帮助你在最快的时间内找到问题所在,从而解决程序上的问题是非常有帮助的。
2.python中常见的错误
NameError:尝试访问一个未申明的变量
ZeroDivisionError:除数为零
SyntaxError:Python解释器语法错误
IndexError:请求的索引超出序列范围
KeyError:请求一个不存在的字典关键字
IOError:输入/输出错误
AttributeError:尝试访问未知的对象属性
3. 检测和异常处理
1.异常可以通过try语句来检测。任何在try语句块里的代码都会被监测,检查有无异常发生。
2.try语句有两种主要形式:try-except和try-finally。这两个语句是互斥的,也就是说你只能使用其中的一种。一个try语句可以对应一个或多个except子句,但只能对应一个finally子句,或是一个try-except-finally复合语句。
3.你可以使用try-except语句检测和处理异常。你也可以添加一个可选的else子句处理没有探测到异常的执行的代码。而try-finally只允许检测异常并做一些必要的清除工作(无论发生错误与否),没有任何异常处理设施。正如你想像的,复合语句两者都可以做到。
二. 相关代码解释
1
try:
number = input('请输入一个数字')
number = int(number)
except Exception as e:
print(e)
解释语句
在程序运行时,解释器尝试执行try块里的所有代码,如果代码块完成后没有异常发生,执行流就会忽略except语句继续执行。而当except语句所指定的异常发生后,我们保存了错误的原因,控制流立即跳转到对应的处理器(try子句的剩余语句将被忽略),本例中我们显示出一个包含错误原因的错误信息。
在我们上边的例子中,我们只捕获 ValueError 异常。任何其他异常不会被我们指定的处理器捕获。举例说,如果你要捕获一个特定的异常,你必须加入一个特定的异常处理器。
try语句块中异常发生点后的剩余语句永远不会到达(所以也永远不会执行)。一旦一个异常被引发,就必须决定控制流下一步到达的位置。剩余代码将被忽略,解释器将搜索处理器,一旦找到,就开始执行处理器中的代码。
如果没有找到合适的处理器,那么异常就向上移交给调用者去处理,这意味着堆栈框架立即回到之前的那个。如果在上层调用者也没找到对应处理器,该异常会继续被向上移交,直到找到合适处理器。如果到达最顶层仍然没有找到对应处理器,那么就认为这个异常是未处理的,Python解释器会显示出跟踪记录,然后退出。
2. 带有多个 except 的 try 语句
def str_2_float(str_):
try:
return float(str_)
except ValueError:
return '不能将一个 Nan 转化为浮点数'
except TypeError:
return '类型错误,请传入正确的内容'
解释语句
首先尝试执行try子句,如果没有错误,忽略所有的except从句继续执行。如果发生异常,解释器将在这一串处理器(except子句)中查找匹配的异常如果找到对应的处理器,执行流将跳转到这里。
我们的safe_float()函数已经可以检测到指定的异常了。更聪明的代码能够处理好每一种异常。这就需要多个except语句,每个except语句对应一种异常类型。Python支持把except语句串连使用我们将分别为每个异常类型分别创建对应的错误信息,用户可以得到更详细的关于错误的信息。
3.处理多个异常的except语句
def str_2_float(str_):
try:
return float(str_)
except (ValueError, TypeError):
return '参数必须是一个数字或者是一个字符串数字'
代码解释
我们还可以在一个except子句里处理多个异常。except语句在处理多个异常时要求异常被放在一个元组
里:上边的语法展示了如何处理同时处理两个异常。事实上except语句可以处理任意多个异常,前提只是它
们被放入一个元组里,
4.捕获所有异常
try:
pass
except Exception as e:
pass
代码解释
我们没有指定任何要捕获的异常——这不会给我们任何关于可能发生的错误的信息。另外它会捕获所有异常,你可能会忽略掉重要的错误,正常情况下这些错误应该让调用者知道并做一定处理。最后,我们没有机会保存异常发生的原因。当然,你可以通过sys.exc_info()获得它,但这样你就不得不去导入sys模块,然后执行函数——这样的操作本来是可以避免的,尤其当我们需要立即告诉用户为什么发生异常的时候。在Python的未来版本中很可能不再支持空except子句(参见“核心风格”)。
很明显,错误无法避免,try-except的作用是提供一个可以提示错误或处理错误的机制,而不是一个错误过滤器。上边这样的结构会忽略许多错误,这样的用法是缺乏工程实践的表现,我们不赞同这样做。
底线:避免把大片的代码装入try-except中然后使用pass忽略掉错误。你可以捕获特定的异常并忽略它们,或是捕获所有异常并采取特定的动作。不要捕获所有异常,然后忽略掉它们。
5.finally子句
try:
A
except Exception as e:
B
finally:
C
代码解释
finally都是可选的。A、B、C是程序(代码块)。程序会按预期的顺序执行。(注意:可能的顺序是AD[正常]或AD[异常])。无论异常发生在Α、Β和/或C都将执行finally块。旧式写法依然有效,所以没有向后兼容的问题。
6.else子句
try:
pass # 尝试做
except Exception as e:
pass # 报错
else:
pass # except没有执行,就执行else
finally:
pass # 最终做
代码解释
我们已经看过else语句段配合其他的Python语句,比如条件和循环。至于try-except语句段,它的功能和你所见过的其他else没有太多的不同:在try范围中没有异常被检测到时,执行else子句。在else范围中的任何代码运行前,try范围中的所有代码必须完全成功(也就是,结束前没有引发异常)。
三. 完整的格式
try:
pass # 尝试做
except ValueError as e:
pass # 捕获一个错误
except (TypeError, SyntaxError) as e:
pass # 捕获多个错误
except Exception as e:
pass # 捕获其他错误
else:
pass # 没有捕捉到错误
finally:
pass # 最终都会执行
总结:
回顾上面,finally子句和try-except或try-except-else联合使用。这一节最重要的是无论你选择什么语法,你至少要有一个except子句,而else和finally都是可选的。
四. 知识点的总结