python的异常机制

本文详细介绍了Python的异常处理机制,包括异常是什么、如何自主抛出异常、自定义异常类、异常捕获、异常对象、异常传播、finally语句的使用以及警告的处理。通过示例代码展示了try/except、raise、自定义异常类、多异常捕获、finally清理工作以及警告过滤器的操作。
摘要由CSDN通过智能技术生成

Table of Contents

1 异常是什么

2如何自主地抛出异常

3 如何自定义异常类

4捕获异常

5捕获对象

6当没有出现异常的时候

7finally

8警告


在编写程序的时候,有时候会遇到程序异常的情况。譬如对0进行整除,我们可以对每个运算都进行条件判断,然而这种做法效率低且灵活性很差,使得代码冗杂,生涩难读。这时候,可以用python提供的「异常处理机制」。

 

1 异常是什么

在介绍这个机制之前,先必须明了,异常是什么?

在自然语言中,「异常」是正常情况以外的情异常况,具有不确定性。python使用异常对象来表示异常状态,每个异常都是某个异常类的实例,这一点和java类似。

2如何自主地抛出异常

通常,当我们写的程序出现不可预测的问题时,都会自动引发异常。那么如何自主地抛出异常呢?

要引发异常使用的是raise语句,并将一个Exception类或者他的子类作为参数。例如:

>>> raise Exception('这里写提示信息')

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

Exception: 这里写提示信息

 

在java中所有的异常类的祖先类都是Exception,这一点python也几乎是一样的。

python内置了一些异常类,他们都可以作为raise语句的参数。

类名

描述

Exception

几乎所有的异常类都是她的子类

AttributeError

引用属性或者给他赋值的时候失败

OSError

操作系统无法执行指定的任务

IndexError

访问序列中不存在的索引

KeyError

使用映射中不存在的Key

NameError

找不到变量的名称

SyntaxError

代码不正确

TypeError

将内置操作或者函数用于类型不正确的对象

ValueError

内置操作或者函数的对象类型正确但值错误

以上只是一些常用的内置异常。

3 如何自定义异常类

虽然内置异常的涉及范围很广,但有时我们想使用自己的异常类。如何自定义异常类?

异常类必须直接或者间接继承Exception,例如:

>>> class MyException(Exception): pass

4捕获异常

异常捕获一般使用try/exception语句,例如:
 

try:
    x=int(input('input N'))
    if (x==0):
        raise Exception
    y=np.log(x)
except Exception:
    print('N can not be zero')
exception … :
…

异常从函数的内部向外部传播,如果在函数内不捕获,在调用函数的地方也可以捕获。但如果在函数内捕获了,外部就无法捕获了。

当我们在函数内捕获了异常,并且还想让他继续传播到调用函数的地方,可以在捕获的时候调用raise,例如:

>>> try:
... 1/0
... except ZeroDivisionError:
... raise
...
Traceback (most recent call last):
File "<stdin>", line 2, in <module>
ZeroDivisionError: division by zero

 

当给raise加上参数的时候,发生了:

>>> try:

... 1/0

... except ZeroDivisionError:

... raise ValueError

...

Traceback (most recent call last):

File "<stdin>", line 2, in <module>

ZeroDivisionError: division by zero


During handling of the above exception, another exception occurred:


Traceback (most recent call last):

File "<stdin>", line 4, in <module>

ValueError

 

正如解释器所说的,在处理当前异常的时候,另一个异常也被捕获了。这是因为1/0引发的ZeroDivisionError异常被当作ValueError异常的上下文存储起来了。

可以使用语句 raise … from … 来自己提供异常上下文,例如:

>>> try:

... 1/0

... except ZeroDivisionError:

... raise ValueError from TypeError

...

TypeError

The above exception was the direct cause of the following exception:

Traceback (most recent call last):

File "<stdin>", line 4, in <module>

ValueError

 

根据提示信息可知,‘from’后的 异常是‘raise’后的异常的直接原因。

当使用‘raise … from None’时,可以消除上下文的关联。

在上面的一个例子中,曾经给出了多个except语句来捕获不同的异常,例如:
 

try:

…

except ZeroDivisionError:

…

except ValueError:

…

当我们想要用一个excep语句捕获多个异常的时候,可以在一个元组中指定这些异常,例如:


 

try:

…

except (ZeroDivisionError,… ):

…

 

5捕获对象

当我们想要访问异常的对象的时候,可以在异常类后面增加一个参数,例如:
 

>>> try:

... 'x'/0

... except (ZeroDivisionError,TypeError) as e:

... print(e)

...

unsupported operand type(s) for /: 'str' and 'int'

 

可以看到,上述的式子出发了两个异常,但最终捕获的只有一个,这是因为异常机制只捕获最近产生的异常,Traceback (most recent call last)。

 

 

6当没有出现异常的时候

 

在有些情况下,我们不会出发任何异常,这样就可以仿照条件语句,添加一个else语句:

>>> try:

... x=1/2

... except:

... print("exception occured")

... else:

... print("万事大吉")

...

万事大吉

 

7finally

我想在设计外卖平台的时候的时候,一个点单行为一般会先产生一个订单,然后跳转到支付界面,当用户完成支付,商家确认之后,这条订单才算真正完成。

然而,在订单产生之后的各个环节都有可能出现异常,譬如用户没有支付或者支付失败。这时候就可以用final语句,来删除这条订单。

finally子句可以用于发生异常时执行清理工作,它可以捕获所有的异常。

譬如上面的例子:

try:

一个订单X产生

支付

商家确认

finally:

删除订单

上面这个例子是我现编的,不知道真实的公司会不会这么草率地删除一项记录。

不过finally真的非常适合用于确保文件或者网络套接字等关掉。

8警告

编程的时候会遇到一些警告,警告类似于异常。但他们通常都是只打印一条错误消息。

例如:


>>> import warnings as win

>>> win.warn("this is a warning")

__main__:1: UserWarning: this is a warning

>>> win.warn("this is second warning")

__main__:1: UserWarning: this is second warning

>>> win.warn("this is a warning")

警告只显示一次,如果再次运行一次win.warn("this is a warning"),是不会显示警告内容的。

每当生成一个警告时,都需要将其与注册过的过滤器比较,第一个匹配的过滤器将控制这个警告采取的动作,否则采取默认的动作,其实本质流程上会发现与Exception异常处理类似,看一下常见的过滤器动作:

error

将警告提升为异常

ignore

忽略警告

always

总是抛出警告

default

从各个位置第一次生成警告时输出警告

module

从各个模块第一次生成警告时输出警告

once

第一次生成警告时输出警告

有时候的一些警告没有什么特殊的意义,我们可以使用函数将他们抑制,例如:

>>> win.filterwarnings("ignore")

>>> win.warn("this is second warning ")

>>> win.warn("this is second warning ")

Traceback (most recent call last):

File "<stdin>", line 1, in <module>

UserWarning: this is second warning 

 

上面分别展示了ignore和error两种状况,分别将警告忽略或者转成错误。

一般而言,一个警告只出现一次,但是使用always可以让他每次执行都出现,

>>> win.warn("this is third warning",)

__main__:1: UserWarning: this is third warning

>>> win.warn("this is third warning",)

__main__:1: UserWarning: this is third warning
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值