Python中異常處理


1、異常 Exception

錯誤Error

邏輯錯誤:算法寫錯了,加法寫成了減法。

筆誤:變量名寫錯了,語法錯誤。

錯誤可以避免的

 

異常Exception

本身就是意外情況。一些意外,導致程序無法正常的執行下去。

是不可避免的。

 

錯誤和異常

在高級編程語言中,一般都有錯誤和異常的概念,異常是可以捕獲的並被處理的,但是錯誤是不能捕獲的。

with open('test') as f:
    pass

 

錯誤信息:

Traceback (most recent call last):

  File "C:/Users/WCL/PycharmProjects/untitled1/package/test1/異常處理.py", line 1, in <module>

    with open('test') as f:

FileNotFoundError: [Errno 2] No such file or directory: 'test'

 

def 0A():
    pass

 

  File "C:/Users/WCL/PycharmProjects/untitled1/package/test1/參數檢查.py", line 142

    class typeassert

                   ^

SyntaxError: invalid syntax

 

一個健壯的程序,盡可能的避免錯誤。

盡可能的捕獲,處理各種異常。

 

2、產生異常

產生:raise語句顯示的拋出異常。

Python解釋器自己檢測到異常並引發他。

def foo():
    print('-----')
    def bar():
        print(1/0)
    bar()
    print('after')
foo()

def bar():
    print('+++++++++++++')
    raise Exception('Exc')
    print('+-+-+-+-+-+')
bar()

 

程序會在異常拋出的地方中斷執行,如果不進行捕獲,就會提前結束程序。

 

raise語句

raise后什么都沒有,表示拋出最近一個被激活的異常,如果沒有被激活的異常,則拋出類型異常。很少利用的方式。

raise

后要求應該是BaseException類的子類或實例,如果是類,將被無參實例化。

異常必須出自BaseException

sys.exc_info()查看異常所在的元素。

sys.exc_info() ,后面是個元組。(異常類、異常對象,trackback)

 

 

3、異常捕獲

try:

  待捕獲異常的代碼塊  

except[異常類型]:

異常的處理代碼塊

 

try:
    print('++++++++++++++++')
    c = 1/0
    print('----------------')
except:
    print('catch the exception')
print('outer')

 

++++++++++++++++

catch the exception

Outer

執行到c = 1/0時候產生異常並拋出,由於使用了語句捕捉這個異常,所以產生異常位置后面的語句將不再執行了,轉而執行對象except以外的語句。

2)捕獲指定類型的異常。

try:
    print('++++++++++++++++')
    c = 1/0
    print('----------------')
except ArithmeticError:
    print('catch the ArithmeticError:')
print('outer')

 

 

++++++++++++++++

catch the ArithmeticError:

Outer

 

 

 

 

 

特別關心的異常放在最上面。

自己定義的異常。

Exception 非退出性異常。

捕獲原則:

4、異常類即繼承層次

def exc_hierarchy(exc=BaseException, level=-1):
    name = exc.__name__
    if level == -1:
        print(name)
    else:
        print("{} +-- {}".format('    ' * level, name))
    for sub in exc.__subclasses__():
        exc_hierarchy(sub, level+1)

 

BaseException

 +-- Exception

     +-- StopAsyncIteration

     +-- OSError

         +-- BlockingIOError

         +-- FileNotFoundError

         +-- IsADirectoryError

         +-- TimeoutError

         +-- InterruptedError

         +-- ProcessLookupError

         +-- NotADirectoryError

         +-- ConnectionError

             +-- BrokenPipeError

             +-- ConnectionAbortedError

             +-- ConnectionRefusedError

             +-- ConnectionResetError

         +-- UnsupportedOperation

         +-- FileExistsError

         +-- ChildProcessError

         +-- PermissionError

     +-- ArithmeticError

         +-- FloatingPointError

         +-- OverflowError

         +-- ZeroDivisionError

     +-- AttributeError

     +-- SyntaxError

         +-- IndentationError

             +-- TabError

     +-- SystemError

         +-- CodecRegistryError

     +-- ImportError

         +-- ZipImportError

     +-- BufferError

     +-- LookupError

         +-- IndexError

         +-- KeyError

         +-- CodecRegistryError

     +-- NameError

         +-- UnboundLocalError

     +-- TypeError

     +-- error

     +-- StopIteration

     +-- AssertionError

     +-- Warning

         +-- UserWarning

         +-- DeprecationWarning

         +-- UnicodeWarning

         +-- PendingDeprecationWarning

         +-- ImportWarning

         +-- RuntimeWarning

         +-- ResourceWarning

         +-- SyntaxWarning

         +-- BytesWarning

         +-- FutureWarning

     +-- Error

     +-- ValueError

         +-- UnicodeError

             +-- UnicodeEncodeError

             +-- UnicodeDecodeError

             +-- UnicodeTranslateError

         +-- UnsupportedOperation

     +-- ReferenceError

     +-- RuntimeError

         +-- RecursionError

         +-- NotImplementedError

         +-- _DeadlockError

     +-- MemoryError

     +-- EOFError

 +-- GeneratorExit

 +-- KeyboardInterrupt

 +-- SystemExit

 

 

 

 

5、BaseException及子類

1)BaseException所有內建異常類的基類是BaseException。

 

2)SystemExit

sys.exit()函數引發的異常,異常不捕獲處理,就直接交給Python解釋器,解釋器退出。

 

import sys
print('++++')
sys.exit(1)
print('sysexit')
print('-----')

 

++++

 

Process finished with exit code 1

未進行捕獲的情況下,

解釋器直接退出了。

 

 

import sys
try:
    print('++++')
    sys.exit(1)
except SystemExit:
    print('sysexit')
print('-----')

 

++++

sysexit

-----

捕獲的情況下正常執行,且被捕獲。

 

3)Keyboardinterrupt

對應捕獲用戶中斷的行為 Ctrl + c

 

6、Exception及子類

Exception是所有內建的,非系統退出的異常的基類,自定義異常應該定義繼承自它。

 

1)SyntaxError語法錯誤,Python中也歸到Exception類中,但是語法錯誤是不可被捕獲的。

2)ArithmeticError所有算數計算引發的異常,其子類有除零異常等。

3)LookupError 使用映射的鍵或者序列的索引無效是引發的異常的基類:indexerror keyerror

4)自定義的異常:從Exception繼承的類。

 

7、異常的捕獲

Except可以捕獲多個異常。

捕獲的原則:捕獲是從上到下依次比較,如果匹配,則執行匹配的except語句塊。

如果被一個except語句塊捕獲,其他的except就不會再次捕獲了。

如果沒有任何一個except語句捕獲到這個異常,則該異常向外拋出。

捕獲的原則,從小到大,從具體到廣泛。

8、as子句

被拋出的異常,應該是異常的實例,獲得這個對象的話,使用as子句。

class MyException(Exception):
    def __init__(self,code,message):
        self.code = code
        self.message = message
try:
    raise MyException
except MyException as e:
    print(11111111)
    print('{}{}'.format(e.code,e.message))
except Exception as e:
    print('{}'.format(e))

 

__init__() missing 2 required positional arguments: 'code' and 'message'

raise后面有特定的參數,如果沒有的話就是無參形式。

 

9、finally 子句

Finally 最終,即最后都會是要一定執行的。try.....finally不管有沒有異常都會執行。

Finally中一般都是放置資源的清理,釋放工作的語句。

也可以在finally中再次捕獲異常。

10、finally執行時機

def foo():
    try:
        return 3
    finally:
        print('finally')
    print('---')
print(foo())

 

盡管函數有return返回語句,但是finally語句還是要執行的,最后才返回return語句。

拿的值是最后一個return。

11、異常傳遞

def foo1():
    return 1/0

def foo2():
    print('foo2 ----')
    foo1()
    print('foo2++++')
foo2()

foo2調用了foo1,foo1產生的異常傳遞到了foo2中

異常總是向外層拋出,如果外層沒有處理這個異常,就會繼續向外拋出,如果內層捕獲並處理了異常,外部就不能捕獲的到了。

如果到了最外層還是沒有被處理,就會中斷異常所在的線程的執行。

import threading
import time

def foo1():
    return 1/0

def foo2():
    time.sleep(3)
    print('foo2----')
    foo1()
    print('foo2++++')
t = threading.Thread(target=foo2)
t.start()

while True:
    time.sleep(1)
    print('Everything OK')
    if t.is_alive():
        print('live')
    else:
        print('dead')

 

未進行捕獲異常,異常拋出直接中斷了線程。

sys.exc_info() ,后面是個元組。(異常類、異常對象,trackback)

 

 

 

 

12、try 的嵌套

try:
    try:
        ret = 1/0
    except KeyError as k:
        print(k)
    else:
        print('ok')
    finally:
        print('finally')
except:
    print('c ok')
finally:
    print('fin')

 

內部捕獲不到異常,會向外層傳遞異常。

但是如果內層有且有finally而且其中有return、break語句,否則就不會繼續往外拋出異常。

 

def foo():
    try:
        ret = 1/0
    except KeyError as F:
        print(k)
    finally:
        print('finally a ')
        return   #異常直接被丟棄
try:
    foo()
except:
    print('+++++')
finally:
    print('-------')

 

有return語句,異常直接被丟棄。

 

13、異常的捕獲時機

1)立即捕獲

需要立即返回一個明確的結果


def parse_int(s):
    try:
        return int(s)
    except:
        return 0
print(parse_int('s'))

 

被return直接返回0

2)邊界捕獲

封裝產生了邊界。

(1)一個模塊,用戶調用了這個模塊的時候捕獲異常,異常內部不需要捕獲,處理異常,一旦內部處理了,外部調用者無法感知異常了

(2)Open函數,出現的異常交給調用者處理,文件存在,就不用創建了,看是否修改修改還是刪除。

(3)自己寫了一個類,使用open函數,但是文件出現異常不知道如何處理,就繼續向外層拋出,一般來說最外層也是邊界,必須處理異常,如果不處理的話,線程就會推出。

14、else子句

 else子句,沒有異常發生,則執行。

try:
    ret = 1/0
except ArithmeticError as e:
    print(e)
else:
    print('ok')
finally:
    print('fin')
####division by zero
###fin

 

15、總結

 try:

<語句> #運行別的代碼

except<異常類>:

<語句>  #捕獲某種類型的異常

except<異常類> as <變量名>:

<語句>   #捕獲某種類型的異常並獲得對象

else:

<語句> #如果沒有異常發生

finally:

<語句>  #推出try的時候總會執行

try的工作原理

(1)如果try中語句執行時候會發生異常,搜索except子句,並執行第一個匹配該異常的except子句。

(2)如果try中語句執行時發生異常,卻沒有匹配except子句,異常將被遞交到外層的try,如果外層不處理這個異常,異常將繼續向外層傳遞,如果都不處理該異常,則會傳遞到最外層,如果還沒有處理,就會終止異常所在的線程。

(3)如果try執行時候沒有異常,將執行else子句中的語句。

(4)無論try中是否發生異常,finally子句最終都會執行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM