python异常处理机制中没有()语句_python学习笔记-tip45(异常处理机制--错误处理)

引言

我们用什么语言写项目,其实都会出错,错误有很多种,有我们写的代码本身就有问题,这个时候属于编译错误,有的代码运行的时候有问题,这个属于运行时异常,python其实也有一套自己的异常处理机制。今天我们来学习一下。

解决错误中的一种方式:返回错误码

返回错误码其实是程序员排除错误的一种方式,他们往往会有一个错误码的字典,字典里面记录了什么数字对应着什么错误;然后当程序返回什么码的时候,去再对照之前那个字典,就能够知道什么错误了。

但是错误码其实有一个局限性,就是当我们返回的结果如果和错误码混合在一起,那么久不太好区分了。

为了避免这种问题,我们常用try catch finally(java语言中)等方式进行运行时异常的捕获。

当然python也有类似的。

try...except...finally

我们先试用一下

try:

print('try...')

r=10/0

print('result:',r)

except ZeroDivisionError as e:

print('except:',e)

finally:

print('finally...')

print('END')

大家应该能看懂大概意思,我们来看下实际输出结果

当我们认为某些代码可能会出错时,就可以用try来运行这段代码

如果执行出错,则后续代码不会继续执行,而是直接跳转至except语句块

执行完except后,如果有finally语句块,则执行finally语句块

至此,执行完毕

ok,当然,如果没有错误出现,那么也不会执行except代码块,如下如

(注意:如果想得到整数,那么用"//")

从上面的输出结果,可以看到,不论异常有没有finally一直都会执行,就像java中的一样

那么,如果发生了不同种的错误,是不是可以使用多种except去处理呢?

答案是肯定的!

我们直接来看示例

这个例子中,我们用一个 except 来捕获 ValueError ,一个 except 来捕获 ZeroDivisionError

此外,如果没有错误发生的话,还可以在 except 后添加一个 else: 去执行没有该错误的处理

如下面例子所示

需要注意的是,并不是一个 except 对应一个 else ,而是当所有的 except 都没处理的话,才会执行唯一的 else ,下面的写法是错的

错误写法

Python的错误也是类,所以如果想捕获某一大类的错误,直接捕获大类就好了

所有的错误类,都继承自 BaseException类

使用try...except捕获错误还有一个巨大的好处,就是可以跨越多层调用

请看下方示例:

由此我们发现,有了这个跨越多层调用 except ,大大减少了复杂的 try except finally 代码的使用

调用栈

如果出的错没有处理,那么最终会被 python 解释器捕获,打印一个错误信息,然后程序退出

我们来演示一下

出错的时候,一定要分析错误的调用栈信息,才能定位错误的位置

出了错之后要懂得找打错误的位置,上面的例子错误的位置就在第三行,10/s的位置,找到错误的位置,确定错误的类型,我们就能够解决了

logging类

我们从上面的例子知道了,即使我们不进行异常的捕获,python编译器也会对异常进行处理,我们也能定位到异常的位置,那么还要异常处理干什么?

其实不然,python处理器虽然会处理异常,但是在处理的同时,也将程序终止。

其实我们可以借助logging类去处理,logging类既会想python处理器一样将错误展示出来,也不会终止程序,如下例所示

抛出错误

需要明确的是:

错误是一个 class ,我们捕获的错误其实就是捕获了该 class 的一个实例

所以说,错误并不是凭空出现的,而是有意抛出的

python内置的函数会抛出很多类型的错误,当然我们自己编写的函数也可以抛出错误。

如果要抛出错误,我们可以根据需要,可以定义一个表示错误的 class ,然后选择好继承关系,

最后用 raise 语句抛出一个错误的实例。

比如,现在定义一个错误,让他继承ValueError

class FooError(ValueError):

pass

然后在适当的地方抛出

def foo(s):

if s==0:

raise FooError('Foo Error %s' %s)

return 10/s

这样,当我们调用foo函数时,如果我们传入

0

那么将会抛出FooError的错误,并且打印

“Foo Error 0”

否则的话,则会直接返回 10/s 的返回值

我们来看一下真实的案例演示:

但是,我们只有在必要的时候才会定义我们自己的错误类型,在定义错误类型时,一定要继承对父类,否则会造成麻烦

下面再来看另外一中处理错误的方式:重复抛出错误

由上图,我们可以看出,虽然已经捕获了异常:打印出了FooError!

但是又将之前的异常抛出,这是什么操作呢?

这个操作有的时候很有必要

有的情况下,由于当前函数不知道怎样去处理当前遇到的错误,那么最恰当的方式是往上抛,让顶层调用者去处理。就好比像一个员工遇到了一个棘手的问题不知道怎么处理,那么他最恰当的做法是交给他的上司,如果他的上司也处理不好,那么就会一直往上抛,直到抛给公司的大老板,让大老板去处理

注意用法

raise 如果直接写的话,那么就是把错误直接原封不动的抛给上级

如果raise 后追加别的错误类型的话,其实就完成了把错误转化成另外一个类型额操作了,如

try:

10/s

except ZeroDivisionError as e:

print('ZeroDivisionError')

raise ValueError('ValueError')

当然了,这种转化只要符合逻辑就可以,但是切忌瞎转化。

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cc的r

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

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值