抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

异常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:
    <语句> # 无论是否发生异常都会执行的代码
  1. 如果try中语句执行时发生异常,搜索except子句,并执行一个匹配该异常的except子句;
  2. 如果try中语句执行时发生异常,却没有匹配到except子句,异常将递交到外层的try,如果外层不处理这个异常,异常将继续向外层传递。如果都不处理该异常,则会传递到最外层,如果还没有处理,就终止异常所在的线程;
  3. 如果在try执行时没有发生异常,没有else子句,可执行else子句中的语句;
  4. 无论try中是否发生异常,finally子句最终都会执行;

评论