异常

一般情况下,在Python无法正常处理程序时就会发生一个异常。异常是Python对象,在python中,所有异常都必须是继承BaseException类的实例。当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

异常处理

捕捉异常可以使用try…except…else…finally…语句。其中else和finally子句是可以省略的。格式如下,

1
2
3
4
5
6
7
8
try:
    语句块
except 异常表达式:
    except处理语句块
else:
    else语句块
finally:
    finally语句块

按照如下方式工作;
首先,执行try子句(在关键字try和关键字except之间的语句) 如果没有异常发生,忽略except子句,try子句执行完后,依次执行else子句和finally子句后结束。

如果在执行try子句的过程中发生了异常,那么try子句余下的部分将被忽略。如果异常的类型和 except 之后的名称相符,那么对应的except子句将被执行。最后执行finally子句。

最后一个except子句,可以没有异常表达式,表示它匹配任何异常。 如果一个异常没有与任何的except匹配,那么这个异常将会传递给上层的try中。

一个 try语句可能包含多个except子句,分别来处理不同的特定的异常。最多只有一个分支会被执行。

else子句必须放在所有的 except 子句后面。else从句只会在没有异常的情况下执行,而且它会在finally语句之前执行。

finally字句是在最后一定会被执行的。

例如:

try…except…语句,捕获不能被零除的异常。

1
2
3
4
5
6
try:
    print('try...')
    r = 10 / 0
    print('result:', r)
except ZeroDivisionError as e:
    print('except:', e)

执行以上程序会输出如下结果:

1
2
try...
except: division by zero

try…except…finally…语句,捕获不能被零除的异常。无论是否有异常,finally子句总是最后被执行。

例如:

1
2
3
4
5
6
7
8
try:
    print('try...')
    r = 10 / 0
    print('result:', r)
except ZeroDivisionError as e:
    print('except:', e)
finally:
    print('finally')

执行以上程序会输出如下结果:

1
2
3
try...
except: division by zero
finally

try…except…else…finally…语句语句,捕获不能被零除的异常。有异常时,else子句不会执行。但是finally子句总是最后被执行。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try:
    print('try...')
    r = 10 / 0
    print('result:', r)
except ZeroDivisionError as e:
    print('except:', e)
else:
    print('else')
finally:
    print('finally')

执行以上程序会输出如下结果:

1
2
3
try...
except: division by zero
finally

try…except…else…finally…语句语句,捕获不能被零除的异常。无异常时,else子句会执行。finally子句总是最后被执行。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
try:
    print('try...')
    r = 10 / 1
    print('result:', r)
except ZeroDivisionError as e:
    print('except:', e)
else:
    print('else')
finally:
    print('finally')

执行以上程序会输出如下结果:

1
2
3
4
try...
result: 10.0
else
finally

抛出异常

Python使用raise语句抛出一个指定的异常。

例如:

1
2
3
4
try:
    raise NameError('NoExistValue')
except NameError as e:
    print('except:', e)

执行以上程序会输出如下结果:

1
except: NoExistValue

处理多个异常

可以使用三种方法来处理多个异常。 第一种方法需要把所有可能发生的异常放到一个元组。

例如:

1
2
3
4
try:
    file = open('test.txt', 'rb')
except (IOError, EOFError) as e:
    print("An error occurred. {}".format(e.args[-1]))

执行以上程序会输出如下结果:

1
An error occurred. [Errno 2] No such file or directory: 'test.txt'

第二种方式是对每个单独的异常在单独的except语句块中处理。我们想要多少个except语句块都可以。

例如:

1
2
3
4
5
6
try:
    file = open('test.txt', 'rb')
except EOFError as e:
    print("An EOF error occurred.",e)
except IOError as e:
    print("An error occurred.",e)

执行以上程序会输出如下结果:

1
An error occurred. [Errno 2] No such file or directory: 'test.txt'

第三种方式是except 子句可以省略异常名,以用作通配符。捕获所有异常。

例如:

1
2
3
4
5
6
try:
    file = open('test.txt', 'rb')
except EOFError as e:
    print("An EOF error occurred.",e)
except:
    print("An error occurred.")

执行以上程序会输出如下结果:

1
An error occurred.

如果发生的异常和except子句中的类是同一个类或者是except子句中的类的子类,则异常和except子句中的类是兼容的(但反过来则不成立)。

例如,下面的代码将依次打印 Grandpa, Father, Son

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Grandpa(Exception):
    pass

class Father(Grandpa):
    pass

class Son(Father):
    pass

for instance in [Grandpa, Father, Son]:
    try:
        raise instance()
    except Son:
        print("Son")
    except Father:
        print("Father")
    except Grandpa:
        print("Grandpa")

执行以上程序会输出如下结果:

1
2
3
Grandpa
Father
Son

但是,下面的代码依次打印Grandpa, Grandpa, Grandpa

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
class Grandpa(Exception):
    pass

class Father(Grandpa):
    pass

class Son(Father):
    pass

for instance in [Grandpa, Father, Son]:
    try:
        raise instance()
    except Grandpa:
        print("Grandpa")
    except Son:
        print("Son")
    except Father:
        print("Father")

执行以上程序会输出如下结果:

1
2
3
Grandpa
Grandpa
Grandpa

异常参数

发生异常时,它可能具有关联值,显示异常的相关信息,也称为异常参数 。参数的存在和类型取决于异常类型。

except 子句可以在异常名称后面指定一个变量。这个变量和一个异常实例绑定,它的参数存储在 instance.args 中。为了方便起见,异常实例定义了str() ,因此可以直接打印参数而无需引用 .args 。也可以在抛出之前首先实例化异常,并根据需要向其添加任何属性。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
try:
    raise Exception('spam', 'eggs')
except Exception as inst:
    # 异常实例的类型
    print(type(inst))

    # 异常参数arguments stored in .args
    print(inst.args)

    # __str__方法允许直接打印inst
    print(inst)

    # 异常参数解包
    x, y = inst.args
    print('x =', x)
    print('y =', y)

执行以上程序会输出如下结果:

1
2
3
4
5
<class 'Exception'>
('spam', 'eggs')
('spam', 'eggs')
x = spam
y = eggs

异常处理程序不仅处理 try 子句中遇到的异常,还处理 try 子句中调用(即使是间接地)的函数内部发生的异常。

例如:

1
2
3
4
5
6
7
8
9
#定义引发异常的函数
def this_fails():
    x = 1/0

try:
    #调用函数,函数内部发生异常
    this_fails()
except ZeroDivisionError as err:
    print('调用函数时发生的异常:', err)

执行以上程序会输出如下结果:

1
调用函数时发生的异常: division by zero

转载请注明本网址。