Python 異常

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, OSErrorSyntaxError等, 直接拿來就可以用。
BaseException是所有異常類的基類。詳見內(nèi)置異常

image.png

二是為滿足個人需求的自定義異常類, 這種類必須要直接或間接地繼承 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/excepttry/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.
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 什么是異常 本節(jié)開始介紹之前,先看看如下程序: 是不是很熟悉,這是我們前面經(jīng)常看到的程序運行出現(xiàn)的錯誤。作為Pyt...
    瀧汰泱閱讀 524評論 0 0
  • @Author : Roger TX (425144880@qq.com) @Link : https:/...
    Roger田翔閱讀 4,481評論 0 2
  • Python 異常處理 python提供了兩個非常重要的功能來處理python程序在運行中出現(xiàn)的異常和錯誤。你可以...
    你的python助手閱讀 325評論 0 2
  • 調(diào)試Python程序時,經(jīng)常會報出一些異常,異常的原因一方面可能是寫程序時由于疏忽或者考慮不全造成了錯誤,這時就需...
    有可能_666閱讀 583評論 0 0
  • Python異常處理 異常概念: 異常:就是不正常的情況,程序開發(fā)過程中錯誤和BUG都是補充正常的情況 異常發(fā)生的...
    youngkun閱讀 983評論 0 4

友情鏈接更多精彩內(nèi)容