异常和异常类
Python常见错误
语法错误
源代码存在拼写语法错 误,这些错误导致Python 编译器无法把Python源代 码转换为字节码,故也称 之为编译错误。
>>> print("我爱山大"}
SyntaxError: invalid syntax
运行时错误
• 程序中没有导入相关的模块:NameError
•
程序中包括零除运算
•
打开不存在的文件:
FileNotFoundError
>>> 1/0
ZeroDivisionError: division by zero
逻辑错误
程序可以执行(程序运 行本身不报错),但执行 结果不正确。Python解释 器对此无能为力,需要根据结果来调试判断。
>>> from math import sqrt
>>> a=1;b=2;c=3
>>> x1=-b+sqrt(b**2-4*a*c)/2*a
math domain error
异常处理
简单地说,异常是指程序运行时引发的错误,引发错误的原因有很多,例如除零、
下标越界、文件不存在、网络异常、类型错误、名字错误、字典键错误、 磁盘空
间不足,等等。
代码运行时如果发生了异常,将生成代表该异常的一个对象,并交由
Python
解释器寻找相应的代码来处理这一异常。合理地使用异常处理结果可以使得程序更加健壮,具有更强的容错性,不会因为用户不小心的错误输入或其他运行时原因而造成程序终止。
异常类
所有异常都是基类
BaseException
的派生类,它们都定义在
BaseExceptions
模
块中。
如果这个异常对象没有进行处理和捕捉,程序就会用所谓的回溯(
traceback
,一
种错误信息)终止执行, 这些信息包括错误的名称(例如
NameError
)、原因和
错误发生的行号。
异常类的层次结构
(1)NameError。尝试访问一个未申明的变量。
>>> noname #报错。NameError: name 'noname' is not defined
(2)SyntaxError。语法错误。
>>> int a #报错。SyntaxError: invalid syntax
(3)AttributeError。访问未知对象属性。
>>> a=1
>>> a.show() #报错。AttributeError: 'int' object has no attribute 'show'
(4)TypeError。类型错误。
>>> 11 + 'abc' #报错。TypeError: unsupported operand type(s) for +: 'int' and 'str'
(5)ValueError。数值错误。
>>> int('abc') #报错。ValueError: invalid literal for int() with base 10: 'abc’ (6)ZeroDivisionError。零除错误。
>>> 1/0 #报错。ZeroDivisionError: division by zero
(7)IndexError。索引超出范围。
>>> a=[10,11,12]
>>> a[3] #报错。IndexError: list index out of range
(8)KeyError。字典关键字不存在。
>>> m = {'1':'yes', '2':'no'}
>>> m['3'] #报错。KeyError: '3'
常见的异常类
异常名称
|
描述
|
ZeroDivisionError
|
除
(
或取模
)
零
(
所有数据类型
)
|
NameError
|
未声明
/
初始化对象
(
没有属性
)
|
SyntaxError
|
解释器发现语法错误
|
IndexError
|
序列中不存在的索引
|
KeyError
|
使用映射中不存在的键
|
FileNotFoundError
|
试图打开不存在的文件
|
AttributeError
|
尝试访问未知对象属性
|
IndentationError
|
缩进错误
|
TabError
|
Tab
和空格混用
|
ImportError
|
导入模块
/
对象失败
|
IOError
|
输入
/
输出操作失败
|
AssertionError
|
断言语句失败
|
抛出异常类
大部分由程序错误而产生的错误和异常,一般由
Python
虚拟机自动抛出。
如果判断某种错误情况,则可以创建相应的异常类的对象,并通过
raise
语句抛出
Python
虚拟机出现错误时会自动抛出异常
>>> 1/0
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module> 1/0
ZeroDivisionError: division by zero
使用
raise
语句主动抛出异常
.
>>> if a<0:raise ValueError("数值不能为负数")
#Traceback (most recent call last):
#File "<pyshell#6>", line 1, in <module>
#if a<0:raise ValueError("数值不能为负数")
#ValueError: 数值不能为负数
主动抛出异常类
raise
语句主动抛出一个异常,异常
/
错误对象必须有一个名字,且它们是
Error
或
Exception
类的子类。
raise [exceptionName [(reason)]]
•
exceptionName
指定异常的名字,是
Error
或
Exception
类的子类。
•
reason
对异常的描述。
#实例
>>> if a<0: raise ValueError("数值不能为负数")
使用类名引发异常
当
raise
语句指定异常的类名时, 会创建该类的实例对象,然后引发异常。
raise IndexError
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
raise IndexError
IndexError
通过显示地创建异常类的对象, 直接使用对象来引发异常。
index = IndexError()raise index
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
raise index
IndexError
指定异常的描述信息
当使用
raise
语句抛出异常时,可以给异常类指定描述信息。
raise IndexError("索引下标超出范围")
Traceback (most recent call last):
File "D:/异常.py", line 1, in <module>
raise IndexError("索引下标超出范围")
IndexError: 索引下标超出范围
异常处理
Python
语言采用结构化的异常处理机制。
•
通过
try
语句来定义代码块,以运行可能抛出异常的代码;
•
通过
except
语句,可以捕获特定的异常并执行相应的处理;
•
通过
finally
语句,即保证处理异常,也可在事后清理资源等。
tip:
在try中出现错误代码(报错),不需要管,他会根据报错类型,执行对应的except中的代码块。
finally语句则会用来做收尾工作(可有可无)
常用的异常处理
- 简单异常: try语句+except异常名
- 多个异常: try语句+多个excep异常名
- 所有异常:try语句 +except
- 没有异常: try语句+ except+ else
- 终止行为: try语句+except+finally语句
捕获所有异常情况的方法
当程序中出现大量异常时,捕获这些异常是非常麻烦的。这时,我们可以在
except
子句中不指明异常的类型,这样,不管发生何种类型的异常,都会
执行
except
里面的处理代码。(可以少列很多限制条件)
try:
num1 = input('请输入第1个数:')
num2 = input('请输入第2个数:')
print(int(num1)/int(num2))
# 放在所有except语句最后
except Exception as result:
print('捕获到异常:%s'%result)
未捕获异常
如果
try
语句没有捕获到任何的错误信息,就不再执行任何
except
语句,而
是会执行
else
语句。
try:
num1 = input("请输入第1个数:")
num2 = input("请输入第2个数:")
print(int(num1)/int(num2))
except Exception as result:
print("捕捉到异常:%s"%result)
else:
print("程序正常运行,没有捕捉到异常")
中止行为
在程序中,无论是否捕捉到异常,
都必须要执行某件事情,例如关
闭文件、释放锁等,这时可以提
供
finally
语句处理。通常情况下,
finally
用于释放资源
tip:是否异常均执行。
import time
try:
f = open('test.txt',"w+")
while True:
content = f.read()
if len(content) == 0:
break
time.sleep(2)
print(content)
finally:
f.close()
print('关闭文件')
try-except语句小结
自定义异常
应用场景
前面捕捉的异常都是系统内置的,在某些错误时自动触发。然而程序员有时需要根据自己的需求设定异常。例如,用户注册账户是需要限定用户名、密码等信息的类型和字数。
创建用户自定义异常需要完成如下的工作
创建一个继承Exception类的子类,就是自定义异常类。
当遇到自己设定的错误时,使用raise语句抛出自定义的异常。
实例
class ShortInputException(Exception):
def __init__(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
try:
s = input('请输入 --> ')
if len(s) < 3:
raise ShortInputException(len(s), 3)
except EOFError:
print ('你输入了一个结束标记EOF')
except ShortInputException as x:
print ('ShortInputException: 长度是 %d, 至少应是 %d' % (x.length, x.atleast))
else:
print ('没有异常发生.')
Python官方讲解exception类
断言处理
在程序调试阶段往往需要判断代码执行过程中变量的值或类型等关键信息。
断言相比
print
语句更加灵活和高效,其一般应用于下列情况。
•
前置条件断言:代码执行之前必须具备的特性
•
后置条件断言:代码执行之后必须具备的特性
•
前后不变断言:代码执行前后不能变化的特性
断言的主要功能是帮助程序员调试程序,以保证程序运行的正确性;断言一般
在开发调试阶段使用。即调试模式时断言有效,优化模式运行时,自动忽略
断言。
assert语句
assert
语句又称作断言,指的是
期望用户满足指定的条件
。
当用户定义的约束条件不满足时,会出发
AssertionError
异常,所以
assert
语
句可以当做条件式的
raise
语句。
assert 布尔表达式 ,<描述性字符>||Vif not 布尔表达式:raise AssertionError(<描述性字符串>)
assert
后面紧跟一个布尔表达式,相当于条件。描述性字符串是当条件为
false
时作
为异常的描述信息。
>>> a = 0
>>> assert a!=0,"a的值不能为0"
Traceback (most recent call last):
File "D:/异常.py", line 2, in <module> assert a!=0,"a的值不能为0"
AssertionError: a的值不能为0
实例
程序基本调试方法
在程序实际运行之前,查找和修正其错误的过程称为调试
(debugging)
。
语法错误的调试
对于编辑错误,
Python
解释器会直接剖出异常,用户可以根据异常信息修改
程序的代码。
>>> if 1>2
SyntaxError: invalid syntax
>>> x
NameError: name 'x' is not defined
运行时错误的调试
对于运行时错误,
Python
解释器也会抛出异常,在代码中可以通过
try…except
语 句捕获并处理。如果程序中没有
try…except
,则
Python
解释
器直接打印出异常信息。
>>> f=open("123.txt")
FileNotFoundError: [Errno 2] No such file or directory: '123.txt'
>>> 123+"abc"
TypeError: unsupported operand type(s) for +: 'int' and 'str'
逻辑错误处理的常用方法
•
包括断点跟踪、输出信息等方法
•
有的集成开发环境(
IDE
)可以设置断点,并查看变量等
•
通过
print
语句输出程序运行过程中变量值(跟踪信息),是观察和调试程序运行逻辑正确性的有效方法
单条语句调试
函数调试
传送门:Python全套学习笔记