python的异常处理机制———try-except-else-finally形式

一.什么是异常
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都是可选的。

四. 知识点的总结

  1. 只处理你知道的异常,避免捕获所有异常然后吞掉它们。
  2. 抛出的异常应该说明原因,有时候你知道异常类型也猜不出所以然。
  3. 避免在 except 语句块中干一些没意义的事情,捕获异常也是需要成本的。
  4. 不要使用异常来控制流程,那样你的程序会无比难懂和难维护。
  5. 如果有需要,切记使用 finally 来释放资源。
  6. 如果有需要,请不要忘记在处理异常后做清理工作或者回滚操作。
  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不想做程序猿的员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值