您好,登錄后才能下訂單哦!
Python的異常處理能力非常強大,但是用不好也會帶來負面的影響。我平時寫程序的過程中也喜歡使用異常,雖然采取防御性的方式編碼會更好,但是交給異常處理會起到偷懶作用。偶爾會想想異常處理會對性能造成多大的影響,于是今天就試著測試了一下。
允許使用異常, 但必須小心。
異常是一種跳出代碼塊的正常控制流來處理錯誤或者其它異常條件的方式。
正常操作代碼的控制流不會和錯誤處理代碼混在一起. 當某種條件發生時, 它也允許控制流跳過多個框架. 例如, 一步跳出N個嵌套的函數, 而不必繼續執行錯誤的代碼。
可能會導致讓人困惑的控制流. 調用庫時容易錯過錯誤情況。
異常必須遵守特定條件:
像這樣觸發異常: raise MyException("Error message")
或者 raise MyException
. 不要使用兩個參數的形式( raise MyException, "Error message"
)或者過時的字符串異常( raise "Error message"
)。
模塊或包應該定義自己的特定域的異常基類, 這個基類應該從內建的Exception類繼承. 模塊的異常基類應該叫做”Error”。
class Error(Exception): pass
永遠不要使用 except
: 語句來捕獲所有異常, 也不要捕獲 Exception
或者 StandardError
, 除非你打算重新觸發該異常, 或者你已經在當前線程的最外層(記得還是要打印一條錯誤消息). 在異常這方面, Python非常寬容, except
: 真的會捕獲包括Python語法錯誤在內的任何錯誤. 使用 except: 很容易隱藏真正的bug。
盡量減少try/except塊中的代碼量. try塊的體積越大, 期望之外的異常就越容易被觸發. 這種情況下, try/except塊將隱藏真正的錯誤。
使用finally子句來執行那些無論try塊中有沒有異常都應該被執行的代碼. 這對于清理資源常常很有用, 例如關閉文件。
當捕獲異常時, 使用 as 而不要用逗號. 例如
try: raise Error except Error as error: pass
采取比較簡單直觀的對照實驗。
先定義一個裝飾器,用來計算每個函數執行所需時間:
def timer(func): import time def wrapper(*args, **kwargs): startTime = time.time() f = func(*args, **kwargs) endTime = time.time() passTime = endTime - startTime print "執行函數%s使用了%f秒" % (getattr(func, "__name__"), passTime) return f return wrapper
然后用該裝飾器裝飾測試的函數即可。
再定義一個叫do_something的函數,這個函數中就做一件事,把1賦值給變量a。在每個測試函數中,都會調用這個函數1000000次。
do_something:
def do_something(): a = 1
我根據情況設計了不同的測試組:
測試組1(直接執行耗時操作):
@timer def test1(): for _ in xrange(1000000): do_something()
測試組2(耗時操作放在try中執行,不拋出錯誤):
@timer def test2(): try: for _ in xrange(1000000): do_something() except Exception: do_something() else: pass finally: pass
測試組3(try放耗時操作中,try每一次操作,不拋出錯誤):
@timer def test3(): for _ in xrange(1000000): try: do_something() except Exception: do_something() else: pass finally: pass
測試組4(try放耗時操作中,try每一次操作并進行異常處理(捕捉拋出的特定異常)):
@timer def test4(): zero = 0 for _ in xrange(1000000): try: if zero == 0: raise ZeroDivisionError except ZeroDivisionError: do_something() else: pass finally: pass
測試組5(try放耗時操作中,try每一次操作并進行異常處理(捕捉所有異常 try…except BaseException)):
@timer def test5(): zero = 0 for _ in xrange(1000000): try: if zero == 0: raise ZeroDivisionError except BaseException: do_something() else: pass finally: pass
測試組6(try放耗時操作中,try每一次操作并進行異常處理(捕捉所有異常 不帶任何異常類型)):
@timer def test6(): zero = 0 for _ in xrange(1000000): try: if zero == 0: raise ZeroDivisionError except: do_something() else: pass finally: pass
測試組7(耗時操作放在except中):
@timer def test7(): zero = 0 try: if zero == 0: raise ZeroDivisionError except ZeroDivisionError: for _ in xrange(1000000): do_something() else: pass finally: pass
測試組8(防御式編碼):
@timer def test8(): zero = 0 for _ in xrange(1000000): if zero == 0: do_something()
執行結果
以上就是本文關于Python異常對代碼運行性能的影響實例解析的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。