Note_python(03)

錯誤與異常

  • AttributeError:嘗試訪問未知的對象屬性
eg. 
>>> class myClass(object):
...     pass
...
>>> my = myClass()
>>> my.name = 'Yanta'
>>> my.name
'Yanta'
>>> my.age
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'myClass' object has no attribute 'age'

檢測與處理異常

異常通過try語句檢測,任何在try語句塊裏的代碼都會被檢測,檢查有無異常發生
try語句有兩種主要形式:try-except和try-finally. 這兩個語句是互斥的,也就是說你只能使用其中的一種。一個try語句可以對應一個或者多個except語句,但是隻能對應一個finally語句,或者一個try-except-finally複合語句。
也就是說:以下三種形式任選其一。

1try-except
2try-finally
3try-except-finally

其中可以使用try-except語句檢測和處理異常,也可以添加一個可選的else子句處理沒有探測到異常的執行的代碼。
try-finally只允許檢測異常並作一些必要的清除工作(無論發生錯誤與否),沒有任何異常處理措施。
複合語句,兩者都可以做到。

try-except

try-except語句定義了進行異常監控的一段代碼,並且提供了異常處理的機制。
語法形式:

try:
    try_suite        #監控這裏的異常
except Expection[, reason]:
    expect_suite      #異常處理代碼

eg.

>>> try:
...     os.remove('test01.log')
... except IOError, e:
...     print 'Could not remove the file:', e
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
OSError: [Errno 2] No such file or directory: 'test01.log' #異常報錯

處理多個異常的try-except語句:

>>> try:
...     os.remove('test01.log')
... except OSError, e:
...     print 'No such file or directory: ', e
... except TypeError, e:
...     print 'Type argument Error: ', e
...
No such file or directory:  [Errno 2] No such file or directory: 'test01.log'

捕獲所有異常

1、有些異常不是由於錯誤條件引起的,比如:SystemExit(當前的python程序需要退出)和KeyboardInterupt(用戶按下了Ctrl+C組合鍵)
2、python2.5之後python異常的繼承發生了變化:

  - BaseException
      | - KeyboardInterupt
      | - SystemExit
      | - Exception
          | - (all other current built-in exceptions)所有當前內建異常

這樣,當你有一個Exception處理器後,你不必爲這兩個一場創建額外的處理器。

try:
    :
except Exception, e:
    # handle real errors

如果你確實需要捕捉所有的異常,那麼就需要使用BaseException:

try:
    :
except BaseException, e:
    # handle real errors

切記

不要再try_suite語段填寫入一大段代碼,再用一個通用的except語句過濾掉任何致命的錯誤,忽略他們。
try-except語句不是用來捕捉過濾所有錯誤然後忽略他們。

異常參數

實際上就是保存引發異常的具體信息,一般爲我們上述書寫的try-except與劇中的e:

>>> try:
...     os.remove('test01.log')
... except OSError, e:
...     print 'No such file or directory: ', e
... except TypeError, e:
...     print 'Type argument Error: ', e
...
No such file or directory:  [Errno 2] No such file or directory: 'test01.log'

這個e是OSError異常類的實例,可以調用他的一些屬性來得到詳細信息。也可以調用內置的type()str()來顯示信息:

>>> type(e)
<type 'exceptions.OSError'>
>>> str(e)
"[Errno 2] No such file or directory: 'test01.log'"
>>> print e
[Errno 2] No such file or directory: 'test01.log'
>>> e
OSError(2, 'No such file or directory')
>>> e.__class__
<type 'exceptions.OSError'>
>>> e.__class__.__doc__
'OS system call failed.'
>>> e.__class__.__name__
'OSError'

else語句

在try-except語句段中,else語句只有在try範圍中沒有異常被檢測到時,纔會被執行。而且在else範圍的任何代碼被運行前,try範圍的所有代碼必須被完全執行成功。不能引發異常。
語句格式:

try:
    try_suite
except :
    except_suite
else:
    else_suite

finally語句

finally語句是無論異常是否發生,是否捕捉都會執行的一段代碼。你也可以將finally語句僅僅和try配合使用,也可以與try-except語句配合使用。
其中try-finally語句是無論異常是否發生,finally代碼段都會被執行。
當try代碼段引發一個異常時,會馬上跳轉到finally語句段,然後當finally代碼段被執行完畢後會繼續向上一層引發異常:

>>> try:
...     os.remove('test01.log')
... finally:
...     print '無論如何這裏都會被執行!'
...
無論如何這裏都會被執行!
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
OSError: [Errno 2] No such file or directory: 'test01.log'

切記

若果finally代碼段引發了另一個異常或者由於return、break、continue語法而終止,原來的異常將丟失而且無法重新引發。

>>> try:
...     os.remove('test01.log')
... finally:
...     os.rmdir('test')
...
Traceback (most recent call last):
  File "<stdin>", line 4, in <module>
OSError: [Errno 2] No such file or directory: 'test'
>>>

上下文管理

with語句是用來簡化代碼的,這與用try-except和try-finally福哦想達到的目的前後呼應。try-except和try-finally的一種特定的配合用法是保證共享的資源的唯一分配,並在任務結束時候釋放它。比如文件(數據、日誌、數據庫等)、線程資源、簡單同步、數據庫連接,等等。with語句的目的就是應用在這種場景。
然而,with語句的目的在於從流程圖中巴try、except和fianlly關鍵字和資源分配釋放相關代碼統統去掉,而不是像try-except-finally那樣僅僅簡化代碼爲之所用。
基本語法如下:

  with context_expr [as var]:
      with_suite

with語句涉及到一些內在的處理細節。with語句僅僅支持上下文管理協議的對象,只有內建了“上下文管理”的對象可以和with一起工作。目前支持該協議的對象有:
* file
* decimal.Context
* thread.LockType
* thread.Lock
* thread.RLock
* thread.Condition
* thread.Semaphore
* thread.BoundedSemaphore
一打開文件爲例,with語句會完成準備工作,當完成操作後,會關閉文件。而且無論在這段代碼的開始、中間和結尾是發生日常,都會執行清理的代碼,此外文件仍會自動關閉。eg.

>>> with open('test.log', 'r') as f0:
...     for eachline in f0:
...             print eachline
...
121

weqefse

1rfewf

1rfegvd

1rfvfdfsv cb

fsdvfvc

現在我們來測試f0:

>>> f0
<closed file 'test.log', mode 'r' at 0x7fbe66a25300>
>>> type(f0)
<type 'file'>
>>> f0.closed  #文件是否被關閉
True
>>> f0.name
'test.log'
>>> f0.mode
'r'

與正常代開文件做對比:

>>> ff = open('test.log', 'r')
>>> type(ff)
<type 'file'>
>>> ff.closed   #文件是否被關閉
False
>>> ff.name
'test.log'
>>> ff.mode
'r'
>>> ff.close()
>>> ff
<closed file 'test.log', mode 'r' at 0x7fbe66a25420>
>>> type(ff)
<type 'file'>
>>> ff.name
'test.log'
>>> ff.mode
'r'
>>> ff.closed     #文件是否被關閉
True

觸發異常

Python提供一種機制讓程序員明確的觸發異常,這就是raise語句。
raise語句的一般用法:

raise [SomeException [, args [, traceback]]]

raise語句的用法列表:

斷言

斷言是一套必須等價於布爾真的判定;此外發生異常也就意味着表達式爲假。
斷言通過assert語句來實現,測試一個表達式,如果返回值爲假,則觸發異常。
assert語句語法格式:

assert expression [, arguments]

示例:

>>> assert 1 == 0
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError
>>> try:
...     assert 1 == 0
... except AssertionError, e:
...     e
...
AssertionError()

python內建異常

BaseException   #所有異常的基類
SystemExit  #解釋器請求退出
KeyboardInterrupt   #用戶中斷執行(通常是輸入^C)
Exception   #常規錯誤的基類
StopIteration   #迭代器沒有更多的值
GeneratorExit   #生成器(generator)發生異常來通知退出
StandardError   #所有的內建標準異常的基類
ArithmeticError #所有數值計算錯誤的基類
FloatingPointError  #浮點計算錯誤
OverflowError   #數值運算超出最大限制
ZeroDivisionError   #除(或取模)零 (所有數據類型)
AssertionError  #斷言語句失敗
AttributeError  #對象沒有這個屬性
EOFError    #沒有內建輸入,到達EOF 標記
EnvironmentError    #操作系統錯誤的基類
IOError #輸入/輸出操作失敗
OSError #操作系統錯誤
WindowsError    #系統調用失敗
ImportError #導入模塊/對象失敗
LookupError #無效數據查詢的基類
IndexError  #序列中沒有此索引(index)
KeyError    #映射中沒有這個鍵
MemoryError #內存溢出錯誤(對於Python 解釋器不是致命的)
NameError   #未聲明/初始化對象 (沒有屬性)
UnboundLocalError   #訪問未初始化的本地變量
ReferenceError  #弱引用(Weak reference)試圖訪問已經垃圾回收了的對象
RuntimeError    #一般的運行時錯誤
NotImplementedError #尚未實現的方法
SyntaxError Python #語法錯誤
IndentationError    #縮進錯誤
IndentationError    #縮進錯誤
IndentationError    #縮進錯誤
TabError    #Tab 和空格混用
SystemError #一般的解釋器系統錯誤
TypeError   #對類型無效的操作
ValueError  #傳入無效的參數
UnicodeError    #Unicode 相關的錯誤
UnicodeDecodeError  #Unicode 解碼時的錯誤
UnicodeEncodeError  #Unicode 編碼時錯誤
UnicodeTranslateError   #Unicode 轉換時錯誤
Warning #警告的基類
DeprecationWarning  #關於被棄用的特徵的警告
FutureWarning   #關於構造將來語義會有改變的警告
OverflowWarning  #舊的關於自動提升爲長整型(long)的警告
PendingDeprecationWarning   #關於特性將會被廢棄的警告
RuntimeWarning  #可疑的運行時行爲(runtime behavior)的警告
SyntaxWarning   #可疑的語法的警告
UserWarning #用戶代碼生成的警告

異常與sys模塊

另一種獲取異常信息的途徑是通過sys模塊的exc_info()函數,其提供一個三元組的信息。

>>> try:
...     float('ada1313')
... except:
...     import sys
...     exc_tuple = sys.exc_info()
...
>>> print exc_tuple
(<type 'exceptions.ValueError'>, ValueError('could not convert string to float: ada1313',), <traceback object at 0x7fa699bfc908>)

這個三元組中包含着三個信息:
1、異常類
2、異常類的實例
3、跟蹤記錄對象

發佈了55 篇原創文章 · 獲贊 20 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章