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