python异常处理机制
- 什么是异常与异常处理?
python 程序的执行过程中,当发生错误时会引起一个事件,该事件被称为异常。异常会打断程序的正常执行流程。
异常就是错误,异常会导致程序崩溃并停止运行。因此就需要异常处理,能监控并捕获到异常,将异常部位的程序进行修理使得程序继续正常运行。
在 python 中,异常处理是通过 try ... except
语句来完成的。
try ... except
语句:
try:
可能产生异常的代码块
except:
处理异常的代码块
示例:
# coding:utf-8
try:
print('try:')
100/0
print('never reach here')
except:
print('except:')
print('0 不能作为除数')
结果:
try:
except:
0 不能作为除数
- 处理指定类型的异常:
在 except
关键字后加上异常类型,表示仅处理该类型的异常。
try:
可能产生异常的代码块
except 异常类型:
处理异常的代码块
示例:
# coding:utf-8
try:
print('try:')
100/0
print('never reach here')
except ZeroDivisionError:
print('except ZeroDivisionError:')
结果:
try:
except ZeroDivisionError:
- 处理多种类型的异常:
可以使用多个 except
关键字处理多种类型的异常。
try:
可能产生异常的代码块
except 异常类型1:
处理异常的代码块
except 异常类型2:
处理异常的代码块
...
示例:
# coding:utf-8
import random
def generate_error():
number = random.randint(0, 1)
if number == 0:
100 / 0
else:
file = open('none-exist-file')
try:
print('try:')
generate_error()
print('never reach here')
except ZeroDivisionError:
print('except ZeroDivisionError:')
except IOError:
print('except IOError:')
根据随机数的不同,结果可能是 except ZeroDivisionError
和 except IOError:
。
- 捕获通用异常:
在捕获异常时,不仅可以获取异常类型,还可以获取异常对象。在不确定是哪种异常的情况下,可以使用 except Exception as e
捕获通用异常。
try:
可能产生异常的代码块
except Exception as e:
处理异常的代码块
示例:
# coding:utf-8
import random
def generate_error():
number = random.randint(0, 1)
if number == 0:
100 / 0
else:
file = open('none-exist-file')
try:
print('try:')
generate_error()
print('never reach here')
except Exception as e:
print(e)
这次是将异常对象打印出来,结果可能是 division by zero
或 [Errno 2] No such file or directory: 'none-exist-file'
。
- 捕获具体异常:
在捕获异常时,不仅可以获取异常类型,还可以获取异常对象。在确定是哪种异常的情况下,可以使用 except 异常类型 as e
捕获具体的异常。
try:
可能产生异常的代码块
except 异常类型1 as e:
处理异常的代码块
except 异常类型2 as e:
处理异常的代码块
...
或
try:
可能产生异常的代码块
except (异常类型1, 异常类型2, ...) as e:
处理异常的代码块
示例:
# coding:utf-8
import random
def generate_error():
number = random.randint(0, 1)
if number == 0:
100 / 0
else:
file = open('none-exist-file')
try:
print('try:')
generate_error()
print('never reach here')
except (ZeroDivisionError, IOError) as e:
print(e)
这次是将异常对象打印出来,结果可能是 division by zero
或 [Errno 2] No such file or directory: 'none-exist-file'
。
捕获具体异常时,即使定义了 try ... except
,但如果异常类型没有与 except
指定的具体异常类型对应上,程序仍然会停止运行。
- 常用异常类型:
Exception
是通用异常类型的基类。
异常类型 | 说明 |
---|---|
Exception | 通用异常类型(基类) |
ZeroDivisionError | 不能整除 0 |
AttributeError | 对象没有这个属性 |
IOError | 输入输出操作失败 |
IndexError | 没有当前索引 |
KeyError | 映射中没有这个键 |
NameError | 未声明/初始化对象 |
FileNotFoundError | 文件不存在 |
ModuleNotFoundError | 模块不存在 |
SyntaxError | Python语法错误 |
IndentationError | 缩进错误 |
AssertionError | 断言语句失败 |
SystemError | 系统错误 |
ValueError | 传入的参数错误 |
TypeError | 类型错误 |
try ... else
语句:
在异常处理中,else
关键字用于指定没有异常时执行的代码块。当异常发生时,该代码块不会被执行;
try:
可能产生异常的代码块
except:
处理异常的代码块
else:
没有异常时执行的代码块
示例:
# coding:utf-8
try:
file = open('test.txt')
line = file.readline()
except IOError:
print('except IOError:')
else:
print(line)
file.close()
结果:
except IOError:
try ... finally
语句:
在异常处理中,finally
关键字后面的代码是无论是否发生异常,都一定会执行的代码。
在函数中,即使在 try
或 except
中进行了 return
,finally
中的代码仍然会执行。而且,try
语法至少要有 except
或 finally
中的一个来配合使用。
如果函数中的 try
、except
和 finally
都有 return
,最终会返回 finally
中的 return
指定的返回值。
try:
可能产生异常的代码块
except:
处理异常的代码块
finally:
无论是否发生异常都会执行的代码块
示例:
# coding:utf-8
def test():
try:
100 / 0
except Exception as e:
print('111')
return e
finally:
return 'finally'
print(test())
结果:
111
finally
- 自定义异常与主动抛出异常:
在 python 中,自定义抛出异常的关键字是 raise
,raise
关键字可以将信息以报错的形式主动抛出。
raise
语句有 3 种形式:
形式 | 功能 |
---|---|
raise | 不带任何参数 |
raise Exception | 把异常的名称作为参数 |
raise Exception(info) | 把异常的名称、异常的描述信息作为参数 |
示例:
# coding:utf-8
def test(number):
if number == 100:
raise ValueError('number 不可以是 %s' % number)
return number
def test2(number):
try:
return test(number)
except ValueError as e:
print(e)
test2(100)
结果:
number 不可以是 100
- 自定义异常类:
自定义异常类需要继承 Exception
基类,而且要在构造函数中定义错误信息。
class 自定义异常类名(Exception):
def __init__(self, message):
self.message = message
示例:
# coding:utf-8
class NumberLimitError(Exception):
def __init__(self, message):
self.message = message
def test(number):
if number > 100:
raise NumberLimitError('number 不可以超过 %s' % number)
return number
def test2(number):
try:
return test(number)
except NumberLimitError as e:
return e
print(test2(100))
print(test2(200))
结果:
100
number 不可以超过 200
- 断言
断言用于判断一个表达式,在表达式条件为 False
时触发异常。
在 python 中,断言的关键字是 assert
。assert
表示假定表达式为 True
,不执行任何操作,为 False
时即触发异常。
与 raise
不同,raise
是直接抛出异常,而 assert
会进行判断,当判断结果为 False
时才会抛出异常。
用法:
assert expression, message
参数 expression
表示表达式,一般是判断相等或判断某种数据类型的语句,message
表示具体的错误信息,assert
无返回值。
示例:
# coding:utf-8
class NumberLimitError(Exception):
def __init__(self, message):
self.message = message
def test(number):
assert number <= 100, NumberLimitError('number 不可以超过 %s' % number)
return number
print(test(100))
print(test(200))
结果:
100
AssertionError: number 不可以超过 200
- bug:
bug 是程序中出现的错误,但又没有通过异常去捕获,以至于直接抛出,导致程序的崩溃。