异常Exception
错误Error
逻辑错误: 算法写错了,例如加法写成了减法
笔误: 例如变量名写错了,语法错误
函数或者类使用错误,其实这也属于逻辑错误
总之,错误是可以避免的异常Exception
本意就是意外的情况
这有个前提,没有出现上面说的错训,也就是说程序写的没有问题,但是在某些情况下,会出现一些意外,导致程序无法正常的执行下去。
例如open函数操作一个文件,文件不存在,或者创建文件的时候文件已经在存在了,或者访问一个网络文件,突然断网了,这就是异常,是个意外的情况。错误和异常
在高级编程语言中,一般都有错误和异常的概念,异常是可以捕获的,但是错误是不能被捕获的;
举例,对比异常和错误
# 对比异常和错误
with open('testabcd') as f:
pass
# 异常
# Traceback (most recent call last):
# File "rjfiles/15-class-exception01.py", line 34, in <module>
# with open('testabcd') as f:
# FileNotFoundError: [Errno 2] No such file or directory: 'testabcd'
def 0A():
pass
# 错误
# File "rjfiles/15-class-exception01.py", line 38
# def 0A():
# ^
# syntax error: invalid syntax (错误)
一个健壮的程序:
- 尽可能的避免错误;
- 尽可能的捕获、处理各咱异常;
有错误的情况、代码不会编译完成,而有异常是在执行过种中报错、后面的程序不能正常执行完成;
print('-' * 30)
try:
1/0
except: # catch 抓住异常并处理掉
print('catch exception')
print('=' * 30)
try:
1/0
raise NotImplementedError
except KeyError: # catch 抓住异常并处理掉, isinstance(KeyError, Exception) ,那么这里管不住,继续抛出
print('catch exception')
try:
1/0
raise NotImplementedError
except ZeroDivisionError: #这里出零异常,那么这里管得住,不会继续抛出
print('catch exception')
try:
1/0
raise NotImplementedError
except ArithmeticError: # 这里出算术异常,那么这里管得住,不会继续抛出
print('catch exception')
try:
1/0
raise NotImplementedError
except Exception: # 这里是所有异常的基类,那么这里管得住,不会继续抛出
print('catch exception')
- 在Python中,异常是通过继承自
BaseException
类的子类来实现的,以下是一些常见的异常及其树状结构
BaseException
├── SystemExit
├── KeyboardInterrupt
├── Exception
│ ├── StopIteration
│ ├── StopAsyncIteration
│ ├── ArithmeticError
│ │ ├── FloatingPointError
│ │ ├── OverflowError
│ │ └── ZeroDivisionError
│ ├── AssertionError
│ ├── AttributeError
│ ├── BufferError
│ ├── EOFError
│ ├── ImportError
│ │ └── ModuleNotFoundError
│ ├── LookupError
│ │ ├── IndexError
│ │ └── KeyError
│ ├── MemoryError
│ ├── NameError
│ │ ├── UnboundLocalError
│ ├── OSError
│ │ ├── BlockingIOError
│ │ ├── ChildProcessError
│ │ ├── ConnectionError
│ │ │ ├── BrokenPipeError
│ │ │ ├── ConnectionAbortedError
│ │ │ └── ConnectionRefusedError
│ │ │ └── ConnectionResetError
│ │ ├── FileExistsError
│ │ ├── FileNotFoundError
│ │ ├── InterruptedError
│ │ ├── IsADirectoryError
│ │ ├── NotADirectoryError
│ │ ├── PermissionError
│ │ └── ProcessLookupError
│ ├── ReferenceError
│ ├── RuntimeError
│ ├── NotImplementedError
│ ├── SyntaxError
│ │ └── IndentationError
│ │ ├── TabError
│ ├── SystemError
│ ├── TypeError
│ ├── ValueError
│ │ ├── UnicodeError
│ │ ├── UnicodeDecodeError
│ │ ├── UnicodeEncodeError
│ │ └── UnicodeTranslateError
│ └── Warning
│ ├── DeprecationWarning
│ ├── PendingDeprecationWarning
│ ├── RuntimeWarning
│ ├── SyntaxWarning
│ ├── UserWarning
│ ├── FutureWarning
│ ├── ImportWarning
│ ├── UnicodeWarning
│ └── BytesWarning
└── GeneratorExit
try:
print('+' * 30 )
raise IndexError("我抛出的异常描述")
except IndexError as e:
print('other ~~~',e, type(e), str(e), e.args) # other ~~~ 我抛出的异常描述 <class 'IndexError'> 我抛出的异常描述 ('我抛出的异常描述',)
print('=' * 30)
try:
print('+' * 30 )
open('test00.txt')
except FileNotFoundError as e:
print('other ~~~',e, type(e), str(e), e.args,e.filename) # other ~~~ [Errno 2] No such file or directory: 'test00.txt' <class 'FileNotFoundError'> [Errno 2] No such file or directory: 'test00.txt' (2, 'No such file or directory') test00.txt
print('=' * 30)
finally
无论是否有异常,都会执行,也就是try
语句块中,不管有没有异常,那么finally
下的语句都将被执行
def foo():
f = None
print('-'* 30 )
try:
print('+' * 30 )
f = open('test00.txt')
except FileNotFoundError as e:
print('other ~~~',e, type(e), str(e), e.args,e.filename)
finally:
print('finally ~~~') # 抓住异常也好,没有异常也好,都会执行
if f: # 解决未成功读取文件时,local variable 'f' referenced before assignment 报错,f 被赋值时才会执行
f.close()
print('=' * 30)
foo()
- 总结
try:
<语句> # 运行别的代码
except <异常类>:
<语句> # 如果在try部份引发了'name'异常
except <异常类> as <变量>:
<语句> # 如果引发了'name'异常,获得了对应的异常实例
else:
<语句> # 如果没有异常发生
finally:
<语句> # 无论是否发生异常都会执行的代码
- 如果
try
中语句执行时发生异常,搜索except
子句,并执行一个匹配该异常的except子句; - 如果
try
中语句执行时发生异常,却没有匹配到except子句,异常将递交到外层的try,如果外层不处理这个异常,异常将继续向外层传递。如果都不处理该异常,则会传递到最外层,如果还没有处理,就终止异常所在的线程; - 如果在
try
执行时没有发生异常,没有else
子句,可执行else
子句中的语句; - 无论
try
中是否发生异常,finally子句最终都会执行;