Python中如何处理异常?Python异常的处理

7.3 异常处理

异常不可怕,关键是要去处理异常。有些异常是在编写中能够预料到的,比如如果想要让用户输入2个数字进行运算,那么就要考虑到用户可能会输入除数为0或者输入字符串的情况。
程序员在编写代码时要考虑到用户的这种可能引起异常的操作,从而通过相应的处理规避异常。

7.3.1 用try…except语句来捕获异常进而进行处理

在之前的章节Python复合语句中我们就已经接触到try…except语句了。这个语句就是用来捕获异常的。在这里我们再复习一下。
try语句完整的命令包括:try、except、else和finally子语句
try子语句跟着的是可能会出现运行异常的命令。
except子语句跟着的是可能会出现的异常类型(可以有多个),捕获到了后就执行。
else子语句跟着的是try子语句没有出现异常将要执行的命令
finally子语句是一定要执行的命令。

捕获异常的要点:
1、所有的异常会一层一层地往上传递。
2、异常类型也是类,Exception异常是所有异常的基类(所有的异常继承于异常)。
3、如果不知道会产生什么异常,就可以用Exception这个基类,或者干脆不写异常类型,这将捕获所有的异常(可以这样做,但不推荐)。
4、其它异常类也有继承关系,一旦有except捕获到了,则其它的except子语句将不再继续捕获异常。因此在写except子语句顺序上必须要注意,范围小的异常类型一定要写在前面。
5、如果想知道异常的详细信息,可以使用traceback模块。使用方式为:traceback.print_exc()

异常继承

以下通过一些示例来对上面的要点进行说明:
异常地传递

def fun1():
    print(1)
    print(1/0)


def fun2():
    print(2)
    fun1()


fun2()

Traceback (most recent call last):
File “E:\BaiduNetdiskWorkspace\FrbPythonFiles\study\test1.py”, line 11, in
fun2()
File “E:\BaiduNetdiskWorkspace\FrbPythonFiles\study\test1.py”, line 8, in fun2
fun1()
File “E:\BaiduNetdiskWorkspace\FrbPythonFiles\study\test1.py”, line 3, in fun1
print(1/0)
ZeroDivisionError: division by zero
2
1

如上所示代码,第3行的print(1/0)报错传递给第8行的fun1(),然后再传递到第11行的fun2()。

用Exception捕获所有的异常

try:
    1/0
except Exception:
    print('catch')

catch

try:
    print(b)
except Exception:
    print('catch')

catch

不指定要捕获的异常类(默认捕获所有的异常)

try:
    1/0
except:
    print('catch')

catch

捕获时异常类型顺序问题

try:
    1/0
except ArithmeticError:
    print('arit')
except ZeroDivisionError:
    print('zero')

arit

如上代码,ZeroDivisionError永远不会被捕获到,因为ZeroDivisionError是ArithmeticError子类,ArithmeticError永远是优先进行捕获。
在实际使用中,一定要将ZeroDivisionError捕获写在ArithmeticError前面。

获取异常的详细信息

import traceback

try:
    100/0
except:
    traceback.print_exc()

Traceback (most recent call last):
File “E:\BaiduNetdiskWorkspace\FrbPythonFiles\study\test1.py”, line 4, in
100/0
ZeroDivisionError: division by zero

7.3.2 触发异常

raise 语句支持强制触发指定的异常。让我们来看2个Python官网的例子:
>>> raise NameError(‘HiThere’)

Traceback (most recent call last):
File “”, line 1, in
NameError: HiThere

raise 唯一的参数就是要触发的异常。这个参数必须是异常实例或异常类(派生自 Exception 类)。如果传递的是异常类,将通过调用没有参数的构造函数来隐式实例化:
>>> raise ValueError # shorthand for ‘raise ValueError()’
如果只想判断是否触发了异常,但并不打算处理该异常,则可以使用更简单的 raise 语句重新触发异常:

try:
    raise NameError('HiThere')
except NameError:
    print('An exception flew by!')
    raise

An exception flew by!
Traceback (most recent call last):
File “”, line 2, in
NameError: HiThere

7.3.3 自定义异常

除了Python自带的异常外,开发者为了方便还可以自定义异常类。但是不论是以直接还是间接的方式,异常都应从 Exception 类派生。
异常类可以被定义成能做其他类所能做的任何事,但通常应当保持简单,它往往只提供一些属性,允许相应的异常处理程序提取有关错误的信息。
大多数异常命名都以 “Error” 结尾,类似标准异常的命名。
许多标准模块都需要自定义异常,以报告由其定义的函数中出现的错误。
自定义异常类

class myError(Exception):
    pass


try:
    print('test')
    raise myError('found error')
except myError as err:
    print('catch')
    print(err)

test
catch
found error

通过自定义异常类,可以让我们在编写程序时,在特定的情况下,用raise语句引发自定义异常,然后再捕获。这样就可以更好的知晓程序运行情况并且可以做相应的异常处理。

7.3.4 错误无法被捕获

因为错误是在解释时没有通过解释器,因此没有进入到程序执行的阶段,所以错误是无法被捕获的。如下:

try:
a = 1/0
    print('我是一只小小鸟)
except SyntaxError:
    print(1)
except ZeroDivisionError:
    print(2)
File "E:\BaiduNetdiskWorkspace\FrbPythonFiles\study\test1.py", line 3
  print('我是一只小小鸟)
        ^

SyntaxError: unterminated string literal (detected at line 3)

这个例子可以很好地区分错误和异常。我们看到结果是报:SyntaxError错误,这是因为代码先进行解释,然后发现了SyntaxError错误。这就说明这段代码没有执行,否则应该会先捕获到ZeroDivisionError错误。

猜你喜欢

转载自blog.csdn.net/crleep/article/details/129650144
今日推荐