Python 含有異常處理機制來幫助用戶處理可能發(fā)生的錯誤異常。
1. 異常概念
異常是指Python程序運行過程中遇到的錯誤, 每個異常都是某個異常類的實例。下面實例中未對異常做任何處理,導致程序終止并且拋出錯誤信息。其中TypeError是異常類中的一種。
def test(a=1, b='2'):
return a + b
test()
#result
Traceback (most recent call last):
File "test.py", line 4, in <module>
test()
File "test.py", line 2, in test
return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
2. 拋出異常
Python中拋出異常必須用到raise語句, 后面接上異常類(會自動創(chuàng)建實例)或者異常類的實例。
raise Exception
#result
Traceback (most recent call last):
File "test.py", line 1, in <module>
raise Exception
Exception
#############################
raise Exception()
#result
Traceback (most recent call last):
File "test.py", line 1, in <module>
raise Exception
Exception
#############################
raise Exception('Meet Error.')
#result
Traceback (most recent call last):
File "test.py", line 1, in <module>
raise Exception('Meet Error.')
Exception: Meet Error.
拋出異常的進階:
def test(a=1, b='2'):
return a + b
try:
test()
except Exception as e:
raise
#raise RuntimeError('Raise Error.')
#raise RuntimeError('Raise Error.') from e
#raise RuntimeError('Raise Error.') from None
#result 1
Traceback (most recent call last):
File "test.py", line 5, in <module>
test()
File "test.py", line 2, in test
return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
#result 2
Traceback (most recent call last):
File "test.py", line 5, in <module>
test()
File "test.py", line 2, in test
return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "test.py", line 8, in <module>
raise RuntimeError('Raise Error.')
RuntimeError: Raise Error.
#result 3
Traceback (most recent call last):
File "test.py", line 5, in <module>
test()
File "test.py", line 2, in test
return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "test.py", line 9, in <module>
raise RuntimeError('Raise Error.') from e
RuntimeError: Raise Error.
#result 4
Traceback (most recent call last):
File "test.py", line 10, in <module>
raise RuntimeError('Raise Error.') from None
RuntimeError: Raise Error.
- 第一種: 直接raise, 捕獲異常后,
重新引發(fā)該異常 - 第二種: 拋出RuntimeError,
處理異常時發(fā)生了新的異常,更傾向于新異常與正在處理的異常沒有關系 - 第三種: from e, 指出
新異常是因舊異常直接引起的, 有助于后續(xù)對異常的分析和排查 - 第四種: from None, 明確
禁止異常關聯(lián)
3. 異常類
異常類分兩種, 一是內(nèi)置異常類,如Exception, OSError,SyntaxError等, 直接拿來就可以用。
BaseException是所有異常類的基類。詳見內(nèi)置異常。

二是為滿足個人需求的自定義異常類, 這種類必須要直接或間接地繼承 Exception, 然后根據(jù)需求是否添加方法。
class CaseError(Exception):
pass
raise CaseError('Case is error.')
#result
Traceback (most recent call last):
File "test.py", line 4, in <module>
raise CaseError('Case is error.')
__main__.CaseError: Case is error.
4. 捕獲異常
可以使用try/except來處理可能發(fā)生異常的語句。
4.1 捕獲一種異常
使用try/except + 異常類名來捕獲該異常
def test(a=1, b='2'):
return a + b
try:
test()
except TypeError:
print ('Meet type error.')
#result
Meet type error.
4.2 捕獲多種異常
有時候程序往往出現(xiàn)不止一種異常, 那如何捕獲多個異常呢,有下面的兩種方法。
- 多層次捕獲: 層次分明, 針對不同的異常做不同的處理
注意:后面第二個至第n個類中不能是第一個的子類, 否則該異常永遠都無法被捕獲
def test(a=1, b='2'):
return a + b
try:
test()
except TypeError:
print ('It is type error.')
except NameError:
print ('It is name error.')
#result
It is type error.
- 一起捕獲: 把所有的異常類放在一個元祖里面
def test(a=1, b='2'):
return a + b
try:
test()
except (TypeError, NameError):
print ('Meet error.')
#result
Meet error.
4.3 捕獲所有異常
捕獲所有異常有兩種常見的格式, 分別是try/except 和 try/except Exception。
-
try/except會捕獲所有異常,包含鍵盤中斷(KeyboardInterrupt)和程序退出請求(SystemExit),慎用之??赡軙箂ys.exit() 語句被捕獲,導致無法退出腳本。
import sys
try:
sys.exit(0)
print ('Exit the function.')
except:
print ('Meet error.')
#result
Meet error.
# sleep 的時候,按Ctrl+c
import time
try:
time.sleep(20)
print ('Sleep 20s.')
except:
print ('Meet error.')
#result,^C表示Ctrl+c
^CMeet Error.
-
try/except Exception會捕獲大部分異常,除了鍵盤中斷(KeyboardInterrupt)和程序退出請求(SystemExit),因為它們是從 BaseException ( Exception 的超類)派生而來的。
import sys
try:
sys.exit(0)
print ('Exit the function.')
except Exception:
print ('Meet error.')
#result
退出腳本
###############
import time
try:
time.sleep(20)
print ('Sleep 20s.')
except Exception:
print ('Meet error.')
#result
^CTraceback (most recent call last):
File "test.py", line 4, in <module>
time.sleep(20)
KeyboardInterrupt
5. 獲取更多的異常信息
當捕獲異常的時候, 我們需要獲取更多的信息去定位和解決問題。
這里有三種方式。一是try/except XXX as e, 另外是traceback內(nèi)置模塊,第三是logging內(nèi)置模塊。
1. e表示異常對象
2. print_exc():對異常的輸出
3. format_exc():把異常以字符串的形式返回,print(traceback.format_exc())等同于于traceback.print_exc()
4. print_exception():traceback.print_exc()實現(xiàn)方式就是traceback.print_exception(sys.exc_info())
import sys
import logging
import traceback
def test(a=1, b='2'):
return a + b
try:
test()
except Exception as e:
print ('****** print object e ******')
print ('Exception type is %s.' % type(e))
print ('e is %s.' % e)
print ('****** traceback.print_exc() ******')
traceback.print_exc()
print ('****** traceback.format_exc() ******')
print(traceback.format_exc())
print ('****** traceback.print_exception() ******')
traceback.print_exception(*sys.exc_info())
print ('****** logging_exception() ******')
traceback.print_exception(*sys.exc_info())
###########result###########
****** print object e ******
Exception type is <class 'TypeError'>.
e is unsupported operand type(s) for +: 'int' and 'str'.
****** traceback.print_exc() ******
Traceback (most recent call last):
File "test.py", line 8, in <module>
test()
File "test.py", line 5, in test
return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
****** traceback.format_exc() ******
Traceback (most recent call last):
File "test.py", line 8, in <module>
test()
File "test.py", line 5, in test
return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
****** traceback.print_exception() ******
Traceback (most recent call last):
File "test.py", line 8, in <module>
test()
File "test.py", line 5, in test
return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
****** logging_exception() ******
Traceback (most recent call last):
File "test.py", line 9, in <module>
test()
File "test.py", line 6, in test
return a + b
TypeError: unsupported operand type(s) for +: 'int' and 'str'
6. else 和 finally
try/except ... else舉例: else 在主 try 塊沒有引發(fā)異常時執(zhí)行
def except_test():
try:
print ('Running')
raise Exception('exception raised')
return 0
except Exception:
print('Here have exception')
return 1
else:
print('No exception')
return 2
print (except_test())
#如果沒有發(fā)生異常, 則返回
Running
0
#如果沒有發(fā)生異常,且注釋掉return 0, 則返回
Running
No exception
2
#如果發(fā)生異常,則返回
Running
Here have exception
1
#如果發(fā)生異常,且注釋掉return 1, 則返回
Running
Here have exception
None
由此可見:
- try 中有異常,會直接跳到except語句
- try 中沒有異常, 且沒有return,才會跳到else語句
try/except ... else ... finally舉例:無論是否引發(fā)異常都將執(zhí)行
def except_test():
try:
print ('Running')
raise Exception('exception raised')
return 0
except Exception:
print('Here have exception')
return 1
else:
print('No exception')
return 2
finally:
print ('Do clean work')
return 3
print (except_test())
#如果沒有發(fā)生異常, 則返回
Running
Do clean work
3
#如果沒有發(fā)生異常,且注釋掉return 0, 則返回
Running
No exception
Do clean work
3
#如果沒有發(fā)生異常,且注釋掉return 3, 則返回
Running
Do clean work
0
#如果沒有發(fā)生異常,且注釋掉return 0 和 return 3, 則返回
Running
No exception
Do clean work
2
#如果發(fā)生異常, 則返回
Running
Here have exception
Do clean work
3
#如果發(fā)生異常, 且注釋掉return 3,則返回
Running
Here have exception
Do clean work
1
由此可知:
- try 中不管有沒有異常, 有沒有return, 最終都會運行finally, 且如果finally 中有return,則函數(shù)返回該return
- finally return 優(yōu)先級》try/except return 優(yōu)先級》else return
7. 異常是向上傳播的
在函數(shù)中引發(fā)異常時,異常將傳播到調(diào)用函數(shù)的地方。
def err():
raise Exception('Error.')
def test_err():
err()
def test_err_too():
test_err()
test_err_too()
#result
Traceback (most recent call last):
File "test.py", line 10, in <module>
test_err_too()
File "test.py", line 8, in test_err_too
test_err()
File "test.py", line 5, in test_err
err()
File "test.py", line 2, in err
raise Exception('Error.')
Exception: Error.