區分Exception和Syntax Error
在寫Python程式的時候經常會報錯,報錯通常有以下兩種情況:
- 語法錯誤(Syntax Error): 部分語法錯誤屬于例外
- 例外(Exception)
語法錯誤
語法錯誤也稱為決議錯誤,是最常遇到的一種錯誤
In [1]: while True print('Hello!')
File "<ipython-input-1-5c66e4fd0ae9>", line 1
while True print('Hello!')
^
SyntaxError: invalid syntax
當代碼不符合Python語法的時候就會拋出SyntaxError,
例外
Python用例外物件來表示例外情況,遇到錯誤后,會引發例外,如果例外沒有處理或捕捉,程式就會用traceback終止程式的執行,如果是在多執行緒程式中,則會終止當前執行緒的執行,
In [2]: 1/0
---------------------------------------------------------------------------
ZeroDivisionError Traceback (most recent call last)
<ipython-input-2-05c9758a9c21> in <module>()
----> 1 1/0
ZeroDivisionError: division by zero
除以0時,就會拋出ZeroDivisionError例外(ZeroDivisionError類的一個實體),
例外層次結構
Python 3.5.2中內置例外的類層次結構如下:參考標準庫
BaseException # 所有例外的基類
+-- SystemExit # 程式退出/終止
+-- KeyboardInterrupt # 由鍵盤中斷(通常為Ctrl+C) 生成
+-- GeneratorExit # 由生成器.close()方法引發
+-- Exception # 所有非退出例外的基類
+-- StopIteration # 停止迭代錯誤
+-- StopAsyncIteration # 停止異步迭代錯誤
+-- ArithmeticError # 算數例外的基類
| +-- FloatingPointError # 浮點操作例外
| +-- OverflowError # 溢位導致的例外
| +-- ZeroDivisionError # 對0進行除或取模操作導致的例外
+-- AssertionError # 由assert陳述句引發
+-- AttributeError # 當屬性名稱無效時引發
+-- BufferError # 緩沖區錯誤引發
+-- EOFError # 到達檔案結尾時引發
+-- ImportError # import陳述句失敗
+-- LookupError # 索引和鍵錯誤
| +-- IndexError # 超出序列索引的范圍
| +-- KeyError # 鍵不存在
+-- MemoryError # 記憶體不足
+-- NameError # 無法找到區域或全域名稱
| +-- UnboundLocalError # 未系結的區域變數
+-- OSError # 作業系統錯誤
| +-- BlockingIOError # IO阻塞
| +-- ChildProcessError # 子行程
| +-- ConnectionError # 連接錯誤
| | +-- BrokenPipeError # 管道斷開
| | +-- ConnectionAbortedError # 連接中止
| | +-- ConnectionRefusedError # 連接拒絕
| | +-- ConnectionResetError # 連接重置
| +-- FileExistsError # 檔案已存在
| +-- FileNotFoundError # 檔案不存在
| +-- InterruptedError # 中斷錯誤
| +-- IsADirectoryError # 目錄錯誤
| +-- NotADirectoryError # 非目錄錯誤
| +-- PermissionError # 權限錯誤
| +-- ProcessLookupError # 行程查找錯誤
| +-- TimeoutError # 超時錯誤
+-- ReferenceError # 銷毀被參考物件后仍然使用參考
+-- RuntimeError # 運行時錯誤
| +-- NotImplementedError # 沒有實作的特性
| +-- RecursionError # 遞回錯誤
+-- SyntaxError # 語法錯誤
| +-- IndentationError # 縮進錯誤
| +-- TabError # 使用不一致的制表符
+-- SystemError # 解釋器中的非致命系統錯誤
+-- TypeError # 給操作傳遞了錯誤的型別
+-- ValueError # 無效型別
| +-- UnicodeError # Unicode錯誤
| +-- UnicodeDecodeError # Unicode解碼錯誤
| +-- UnicodeEncodeError # Unicode編碼錯誤
| +-- UnicodeTranslateError # Unicode轉換錯誤
+-- Warning # 警告的基類
+-- DeprecationWarning # 關于被棄用的特征的警告
+-- PendingDeprecationWarning # 關于特性將會被廢棄的警告
+-- RuntimeWarning # 可疑的運行時行為的警告
+-- SyntaxWarning # 可疑的語法的警告
+-- UserWarning # 用戶代碼生成的警告
+-- FutureWarning # 關于構造將來語意會有改變的警告
+-- ImportWarning # import陳述句的警告
+-- UnicodeWarning # Unicode警告
+-- BytesWarning # Bytes警告
+-- ResourceWarning # 資源警告
- 所有例外的基類都是BaseException
- 除SystemExit,KeyboardInterrupt,GeneratorExit三種例外外都繼承自Exception
捕獲例外
捕獲例外可以使用try/except陳述句,try/except陳述句用來檢測try陳述句塊中的錯誤,從而讓except陳述句捕獲例外資訊并處理,
try/except
基礎語法
try:
<陳述句>
except <name>:
<陳述句> #如果在try部分引發了名為'name'的例外,則執行這段代碼
示例
In [3]: try:
...: x = int(input("Please enter a number: "))
...: except ValueError:
...: print("No valid number.")
...:
Please enter a number: asd
No valid number.
多個except
In [4]: import sys
In [5]: try:
...: f = open('file.txt') # 檔案不存在的時候就會拋出FileNotFoundError例外
...: s = f.readline()
...: i = int(s.strip())
...: except OSError: # FileNotFoundError例外的上層例外
...: print('OS error.')
...: except ValueError:
...: print('Could not convert data to integer.')
...: except Exception:
...: print('Exception.')
...: except: # 不加具體例外型別時,會捕獲所有的例外,應該不用或者慎用
...: print('Unexpected error:', sys.exc_info()[0])
...:
OS error.
各個except之間的執行順序:
- except順序捕獲try中拋出的例外
- 越具體的例外應該越靠前,越一般的例外應該越靠后
可選的else陳述句
語法
try:
<陳述句>
except <name>:
<陳述句> #如果在try部分引發了名為'name'的例外,則執行這段代碼
else:
<陳述句> #如果沒有例外發生,則執行這段代碼
如果try部分沒有拋出例外,但是又必須執行的陳述句,則放在else陳述句中,
代碼
for arg in sys.argv[1:]:
try:
f = open(arg, 'r')
except IOError:
print('cannot open', arg)
else: # 沒有拋出例外(即檔案正確打開)時列印出檔案中的每一行
print(arg, 'has', len(f.readlines()), 'lines')
f.close()
finally陳述句
finally陳述句用來定義在任何情況下都必須執行的陳述句,
In [1]: try:
...: raise KeyboardInterrupt
...: finally:
...: print('Goodbye')
...:
Goodbye
---------------------------------------------------------------------------
KeyboardInterrupt Traceback (most recent call last)
<ipython-input-8-132d568ca0fb> in <module>()
1 try:
----> 2 raise KeyboardInterrupt
3 finally:
4 print('Goodbye')
5
KeyboardInterrupt:
帶return陳述句的finally執行順序
def p(x):
print(x)
return x
def t():
try:
return p(2)
print('haha')
finally:
return p(3)
x = t()
# 輸出結果為:
2
3
# 回傳值x為3
可見,在try塊中,只要有finally陳述句,即使函式提前回傳,也會在退出try塊之前執行finally陳述句,因此回傳值會被finally中的return陳述句替代,
綜合使用示例
In [1]: def divide(x, y):
...: try:
...: result = x / y
...: except ZeroDivisionError:
...: print('division by zero!')
...: else:
...: print('result is ', result)
...: finally:
...: print('executing finally clause.')
...:
In [2]: divide(2, 0)
division by zero!
executing finally clause.
In [3]: divide(2, 1)
result is 2.0
executing finally clause.
In [4]: divide('2', '1')
executing finally clause.
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-34bb38fa74fd> in <module>()
----> 1 divide('2', '1')
<ipython-input-1-4273ffa41b76> in divide(x, y)
1 def divide(x, y):
2 try:
----> 3 result = x / y
4 except ZeroDivisionError:
5 print('division by zero!')
TypeError: unsupported operand type(s) for /: 'str' and 'str'
結論:
- 任何情況下finally陳述句都會執行,
- 即使try部分中有return陳述句,也會在退出try塊之前執行finally陳述句,并且回傳值是finally中的return
- 如果有例外沒有被處理,則在執行完成finally陳述句之后會會拋出沒有被處理的例外
- 在實際使用中,finally通常用來釋放額外的資源,比如檔案或者網路連接
主動拋出例外
raise陳述句
In [1]: raise NameError('Hello')
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-64f372e60821> in <module>()
----> 1 raise NameError('Hello')
NameError: Hello
用戶自定義例外
用戶自定義例外類時,應該直接或者間接的繼承自Exception類,
class CustomException(Exception):
def __init__(self, code, message):
self.code = code
self.message = message
try:
raise CustomException(500, 'error')
except CustomException as e:
print('{},{}'.format(e.code, e.message))
# 輸出結果:500,error
例外的傳遞
在函式內引發例外時,如果例外沒有被捕獲到,那么它就會被傳播到函式被呼叫的地方,
In [1]: def a():
...: raise Exception('Hello')
...:
In [2]: def b():
...: print('enter b')
...: a() # 函式a中引發的例外,會傳遞到父函式的呼叫出
...: print('exit b') # a中拋出例外之后傳遞到b,中止b的執行
...:
In [3]: b()
enter b
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
<ipython-input-3-9c619ddbd09b> in <module>()
----> 1 b()
<ipython-input-2-f99a565bd6f8> in b()
1 def b():
2 print('enter b')
----> 3 a()
4 print('exit b')
5
<ipython-input-1-6e68e60e93b5> in a()
1 def a():
----> 2 raise Exception('Hello')
Exception: Hello
記得幫我點贊哦!
精心整理了計算機各個方向的從入門、進階、實戰的視頻課程和電子書,按照目錄合理分類,總能找到你需要的學習資料,還在等什么?快去關注下載吧!!!

念念不忘,必有回響,小伙伴們幫我點個贊吧,非常感謝,
我是職場亮哥,YY高級軟體工程師、四年作業經驗,拒絕咸魚爭當龍頭的斜杠程式員,
聽我說,進步多,程式人生一把梭
如果有幸能幫到你,請幫我點個【贊】,給個關注,如果能順帶評論給個鼓勵,將不勝感激,
職場亮哥文章串列:更多文章

本人所有文章、回答都與著作權保護平臺有合作,著作權歸職場亮哥所有,未經授權,轉載必究!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/146025.html
標籤:Python
下一篇:Cport使用問題
