Python中引进了很多用来描述异常的类,称为异常类。异常类定义中包含了该类异常的信息和对异常的处理方法。Python中内建异常类的继承层次:
Python中一切都是对象,异常也采用对象的方式来处理。处理过程:
- 抛出异常:在执行一个方法时,如果发生异常,则这个方法生成一个代表该异常的对象。停止当前的执行路径,并把异常对象提交给解释器。
- 捕获异常:解析器得到该异常后,寻找相应的代码来处理该异常
try...except结构
try:
被监控的可能引发异常的语句块
except Base Exception [as e]:
异常处理语句块
- try块包含着可能引发异常的代码,except块则用来捕捉和处理发生的异常。
- 执行的时候,如果try块中没有引发异常,则跳过except块继续执行后续代码
- 执行的时候如果try块发生异常,则跳过try块中的后续代码,跳到相应的except块中处理异常;异常处理完后,继续执行后续代码。
try和多个except结构
上面的结构可以捕获所有的异常。但是一般建议尽量捕获可能出现的多个异常(按照先子类后父类的顺序),并且针对性的写出异常处理的代码。为了避免遗漏可能出现的异常,我们在最后增加BaseException。
try:
被监控的、可能引发异常的语句块
except Exception1:
处理Exception1的语句块
except Exception2:
处理Exception2的语句块
...
except BaseException:
处理可能遗漏的异常的语句块
try:
a = input("请输入被除数:")
b = input("请输入除数:")
c = float(a)/float(b)
print(c)
except ZeroDivisionError:
print("异常:除数不能为0")
except ValueError:
print("异常:a和b都应该是数值类型")
except BaseException as e:
print(e)
print(type(e))
try...except...else结构
增加了else块,如果try块中没有抛出异常,则执行else块。如果try块中抛出异常,则执行except块,不执行else块。
try:
a = input("请输入被除数:")
b = input("请输入除数:")
c = float(a)/float(b)
except BaseException as e:
print(e)
else:
print("c:",c)
try...except...finally结构
无论是否发生异常,finally块都会执行;通常用来释放try块中申请的资源。
try:
f = open("e:/01_PythonTest/b.txt",'r')
content = f.readline()
print(content)
except BaseException as e:
print(e)
finally:
"""
释放资源。此处也可能发生异常。
若发生异常,则程序终止,不会继续往下执行
"""
f.close()
print("执行其他代码")
常见异常
异常名称 | 说明 |
ArithmeticError | 所有数值计算错误的基类 |
AssertionError | 断言语句失败 |
AttributeError | 对象没有这个属性 |
BaseException | 所有异常的基类 |
DeprecationWarning | 关于被弃用的特征的警告 |
EnvironmentError | 操作系统错误的基类 |
EOFError | 没有内建输入,到达EOF 标记 |
Exception | 常规错误的基类 |
FloatingPointError | 浮点计算错误 |
FutureWarning | 关于构造将来语义会有改变的警告 |
GeneratorExit | 生成器(generator)发生异常来通知退出 |
ImportError | 导入模块/对象失败 |
IndentationError | 缩进错误 |
IndexError | 序列中没有此索引(index) |
IOError | 输入/输出操作失败 |
KeyboardInterrupt | 用户中断执行(通常是输入^C) |
KeyError | 映射中没有这个键 |
LookupError | 无效数据查询的基类 |
MemoryError | 内存溢出错误(对于Python 解释器不是致命的) |
NameError | 未声明/初始化对象 (没有属性) |
NotImplementedError | 尚未实现的方法 |
OSError | 操作系统错误 |
OverflowError | 数值运算超出最大限制 |
OverflowWarning | 旧的关于自动提升为长整型(long)的警告 |
PendingDeprecationWarning | 关于特性将会被废弃的警告 |
ReferenceError | 弱引用(Weak reference)试图访问已经垃圾回收了的对象 |
RuntimeError | 一般的运行时错误 |
RuntimeWarning | 可疑的运行时行为(runtime behavior)的警告 |
StandardError | 所有的内建标准异常的基类 |
StopIteration | 迭代器没有更多的值 |
SyntaxError | Python 语法错误 |
SyntaxWarning | 可疑的语法的警告 |
SystemError | 一般的解释器系统错误 |
SystemExit | 解释器请求退出 |
TabError | Tab 和空格混用 |
TypeError | 对类型无效的操作 |
UnboundLocalError | 访问未初始化的本地变量 |
UnicodeDecodeError | Unicode 解码时的错误 |
UnicodeEncodeError | Unicode 编码时错误 |
UnicodeError | Unicode 相关的错误 |
UnicodeTranslateError | Unicode 转换时错误 |
UserWarning | 用户代码生成的警告 |
ValueError | 传入无效的参数 |
Warning | 警告的基类 |
WindowsError | 系统调用失败 |
with上下文管理资源
finally块由于是否发生异常都会执行,通常我们放释放资源的代码。其实也可以通过with上下文管理,更方便的实现释放资源的操作。
with上下文管理的语法结构:
with context_expr [as var]:
语句块
with上下文管理可以自动管理资源,在with代码块执行完毕后自动欢迎进入该代码之前的现场和上下文。不论何种原因跳出with块,不论是否有异常,总能保证资源正常释放,极大简化了工作。在文件操作、网络通信相关场合非常常用。
with open("e:/01_PythonTest/a.txt") as f:
for line in f:
print(line)
traceback模块和生成异常日志
将报错信息追加到a.log中
import traceback
try:
num = 1/0
except:
with open("e:/01_PythonTest/a.log","a") as f:
traceback.print_exc(file=f)
自定义异常
有时候需要我们自己定义异常类。自定义异常类一般都是运行时异常,通常继承Exception或其子类即可。命名一般以Error、Exception为后缀。自定义异常由raise语句主动抛出。
class AgeError(Exception):
def __init__(self, errorinfo):
Exception.__init__(self)
self.errorinfo = errorinfo
def __str__(self):
return str(self.errorinfo) + ",年龄错误!应该在1-150之间"
if __name__ == "__main__":
age = int(input("输入年龄:"))
if age < 1 or age > 150:
raise AgeError(age)
else:
print("正常年龄:", age)
输入年龄:155
Traceback (most recent call last):
File "E:\PyProjects\Demo_09.py", line 13, in <module>
raise AgeError(age)
__main__.AgeError: 155,年龄错误!应该在1-150之间
Process finished with exit code 1