raise
try except as
else
finally

异常Exception和错误Error


  • 异常可捕获,可处理。如除 0 异常
  • 错误不能被捕获。如语法错误
  • 为了保证程序的健壮性,应尽可能捕获和处理异常,避免错误
# Python异常的继承
BaseException 
+-- SystemExit 
+-- KeyboardInterrupt 
+-- GeneratorExit 
+-- Exception      
    +-- RuntimeError      
    |    +-- RecursionError      
    +-- MemoryError      
    +-- NameError      
    +-- StopIteration      
    +-- StopAsyncIteration      
    +-- ArithmeticError      
    |    +-- FloatingPointError      
    |    +-- OverflowError      
    |    +-- ZeroDivisionError      
    +-- LookupError      
    |    +-- IndexError      
    |    +-- KeyError      
    +-- SyntaxError      
    +-- OSError      
    |    +-- BlockingIOError      
    |    +-- ChildProcessError      
    |    +-- ConnectionError      
    |    |    +-- BrokenPipeError      
    |    |    +-- ConnectionAbortedError      
    |    |    +-- ConnectionRefusedError      
    |    |    +-- ConnectionResetError      
    |    +-- FileExistsError      
    |    +-- FileNotFoundError      
    |    +-- InterruptedError      
    |    +-- IsADirectoryError
    |    +-- NotADirectoryError      
    |    +-- PermissionError      
    |    +-- ProcessLookupError      
    |    +-- TimeoutError
....
....

BaseException 及子类

  • BaseException
    所有内建异常类的基类
  • SystemExit
    sys.exit() 函数引发的异常
    异常不捕获,直接交给 Python 解释器,解释器退出
    如果捕获异常,则继续向后执行
import sys
try:
    sys.exit(1)
except SystemExit:
    print('system exit')
print('continue execute')
  • KeyboardInterrupt
    捕获用户键盘中断行为
  • Exception

Exception 及其子类

  • Exception 是所有内建的、非系统退出异常的基类
  • 自定义异常应该都继承自 Exception
try:
    <语句>    #运行别的代码
except <异常类>:
    <语句>    # 捕获某种类型的异常
except <异常类> as <变量名>:
    <语句>    # 捕获某种类型的异常并获得对象
else:
    <语句>    #如果没有异常发生
finally:
    <语句>    #退出try时总会执行

捕获规则

  • 捕获是从上到下依次比较,如果匹配到,则执行匹配的 except 语句块
  • 如果被一个 except 语句捕获,其他 except 语句就不会再次捕获了
  • 如果没有任何一个 except 语句捕获到这个异常,则该异常向外抛出
  • 捕获的原则从小到大,从具体到宽泛

raise 抛出异常

# 比较例子1和例子2
# 例1:
class MyException(Exception):
    def __init__(self, code, message):
        self.code = code
        self.message = message

try:
    raise MyException
except MyException as e:
    print('catch my exception')
except Exception as e:
    print(e)
------------------------------------
__init__() missing 2 required positional arguments: 'code' and 'message'

# 例2:
class MyException(Exception):
    def __init__(self, code, message):
        self.code = code
        self.message = message

try:
    raise MyException(200,'ok')
except MyException as e:
    print('catch my exception')
except Exception as e:
    print(e)
---------------------------------
catch my exception
  • raise 抛出的异常应该是 BaseException 类的子类或者实例
  • raise 抛出的异常如果是,则将会被无参实例化
  • 可使用 as 获取异常对象

finally

  • 不管是否发生异常,都要执行 finally 部分语句
  • finally 语句块中一般放置资源的清理、释放
  • 也可在 finally 中再次捕捉异常
  • finally 执行时机:参考如下例子
def foo():
    # return 1
    try:
        return 3
    finally:
        return 5
        # print('finally')
    # print('======')
print(foo()) 
# try语句块执行时,函数虽然要返回,但finally一定还要执行,执行后函数返回5
# 简单理解:函数的返回值取决于最后一个执行的return语句
-------------------
5

else

  • 没有任何异常发生时则执行 else 语句块

异常的传递

  • 异常总是向外层抛出,如果异常被传递到最外层还没有处理,则终止异常所在的线程
  • 如果内层有 finally,且其中有 return、break 语句,则异常就不会继续向外抛出,异常被丢弃
# 线程中测试异常
# 如果异常被传递到最外层还没处理,则终止异常所在的线程
import threading
import time

def foo1():
    return 1 / 0

def foo2():
    time.sleep(2)  # 2秒后抛出异常
    print('foo2 start')
    foo1()
    print('foo2 stop')

t = threading.Thread(target=foo2)
t.start()

while True:
    time.sleep(1)
    print('Everything OK')
    print(threading.enumerate())  # 打印当前所有线程
-----------------------------------------------------------
Everything OK
[<_MainThread(MainThread, started 12208)>, <Thread(foo2, started 17056)>]
foo2 start
Everything OK
<异常栈>
Everything OK
[<_MainThread(MainThread, started 12208)>]
...
...
...
def foo():
    try:
        ret = 1 / 0
    except KeyError as e:
        print(e)
    finally:
        print('inner final')
        return # 异常被丢弃
try:
    foo()
except:
    print('outer catch')
finally:
        print('outer final')
-----------------------------------
inner final
outer final

参考


  • magedu