免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
一文讀懂Python中的異常處理

異常處理語(yǔ)句 try...excpet...finally

實(shí)例代碼

def div(a, b):
   try:
       print(a / b)
   except ZeroDivisionError:
       print('Error: b should not be 0 !!')
   except Exception as e:
       print('Unexpected Error: {}'.format(e))
   else:
       print('Run into else only when everything goes well')
   finally:
       print('Always run into finally block.')
       
# tests
div(2, 0)
div(2, 'bad type')
div(1, 2)

# Mutiple exception in one line
try:
   print(a / b)
except (ZeroDivisionError, TypeError) as e:
   print(e)
   
# Except block is optional when there is finally
try:
   open(database)
finally:
   close(database)
   
# catch all errors and log it
try:
   do_work()
except:    
   # get detail from logging module
   logging.exception('Exception caught!')

   # get detail from sys.exc_info() method
   error_type, error_value, trace_back = sys.exc_info()
   print(error_value)
   raise

總結(jié)如下

  1. except語(yǔ)句不是必須的,finally語(yǔ)句也不是必須的,但是二者必須要有一個(gè),否則就沒(méi)有try的意義了。

  2. except語(yǔ)句可以有多個(gè),Python會(huì)按except語(yǔ)句的順序依次匹配你指定的異常,如果異常已經(jīng)處理就不會(huì)再進(jìn)入后面的except語(yǔ)句。

  3. except語(yǔ)句可以以元組形式同時(shí)指定多個(gè)異常,參見(jiàn)實(shí)例代碼。

  4. except語(yǔ)句后面如果不指定異常類型,則默認(rèn)捕獲所有異常,你可以通過(guò)logging或者sys模塊獲取當(dāng)前異常。

  5. 如果要捕獲異常后要重復(fù)拋出,請(qǐng)使用raise,后面不要帶任何參數(shù)或信息。

  6. 不建議捕獲并拋出同一個(gè)異常,請(qǐng)考慮重構(gòu)你的代碼。

  7. 不建議在不清楚邏輯的情況下捕獲所有異常,有可能你隱藏了很嚴(yán)重的問(wèn)題。

  8. 盡量使用內(nèi)置的異常處理語(yǔ)句來(lái) 替換try/except語(yǔ)句,比如with語(yǔ)句,getattr()方法。

拋出異常 raise

如果你需要自主拋出異常一個(gè)異常,可以使用raise關(guān)鍵字,等同于C#和Java中的throw語(yǔ)句,其語(yǔ)法規(guī)則如下。

raise NameError('bad name!')

raise關(guān)鍵字后面需要指定你拋出的異常類型,一般來(lái)說(shuō)拋出的異常越詳細(xì)越好,Python在exceptions模塊內(nèi)建了很多的異常類型,通過(guò)使用dir()函數(shù)來(lái)查看exceptions中的異常類型,如下:

import exceptions
# ['ArithmeticError', 'AssertionError'.....]
print dir(exceptions)

當(dāng)然你也可以查閱Python的文檔庫(kù)進(jìn)行更詳細(xì)的了解。

https://docs.python.org/2.7/library/exceptions.html#bltin-exceptions

自定義異常類型

Python中也可以自定義自己的特殊類型的異常,只需要要從Exception類繼承(直接或間接)即可:

class SomeCustomException(Exception):
   pass

一般你在自定義異常類型時(shí),需要考慮的問(wèn)題應(yīng)該是這個(gè)異常所應(yīng)用的場(chǎng)景。如果內(nèi)置異常已經(jīng)包括了你需要的異常,建議考慮使用內(nèi)置 的異常類型。比如你希望在函數(shù)參數(shù)錯(cuò)誤時(shí)拋出一個(gè)異常,你可能并不需要定義一個(gè)InvalidArgumentError,使用內(nèi)置的ValueError即可。

經(jīng)驗(yàn)案例

傳遞異常 re-raise Exception

捕捉到了異常,但是又想重新引發(fā)它(傳遞異常),使用不帶參數(shù)的raise語(yǔ)句即可:

def f1():
   print(1/0)
def f2():
   try:
       f1()
   except Exception as e:
       raise  # don't raise e !!!
f2()

在Python2中,為了保持異常的完整信息,那么你捕獲后再次拋出時(shí)千萬(wàn)不能在raise后面加上異常對(duì)象,否則你的trace信息就會(huì)從此處截?cái)?。以上是最?jiǎn)單的重新拋出異常的做法。

還有一些技巧可以考慮,比如拋出異常前對(duì)異常的信息進(jìn)行更新。

def f2():
   try:
       f1()
   except Exception as e:
       e.args += ('more info',)
       raise

如果你有興趣了解更多,建議閱讀這篇博客。

http://www.ianbicking.org/blog/2007/09/re-raising-exceptions.html

Python3對(duì)重復(fù)傳遞異常有所改進(jìn),你可以自己嘗試一下,不過(guò)建議還是同上。

Exception 和 BaseException

當(dāng)我們要捕獲一個(gè)通用異常時(shí),應(yīng)該用Exception還是BaseException?我建議你還是看一下 官方文檔說(shuō)明,這兩個(gè)異常到底有啥區(qū)別呢? 請(qǐng)看它們之間的繼承關(guān)系。

BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
     +-- StopIteration...
     +-- StandardError...
     +-- Warning...

從Exception的層級(jí)結(jié)構(gòu)來(lái)看,BaseException是最基礎(chǔ)的異常類,Exception繼承了它。BaseException除了包含所有的Exception外還包含了SystemExit,KeyboardInterrupt和GeneratorExit三個(gè)異常。

有此看來(lái)你的程序在捕獲所有異常時(shí)更應(yīng)該使用Exception而不是BaseException,因?yàn)榱硗馊齻€(gè)異常屬于更高級(jí)別的異常,合理的做法應(yīng)該是交給Python的解釋器處理。

except Exception as e和 except Exception, e

代碼示例如下:

try:
   do_something()
except NameError as e:  # should
   pass
except KeyError, e:  # should not
   pass

在Python2的時(shí)代,你可以使用以上兩種寫(xiě)法中的任意一種。在Python3中你只能使用第一種寫(xiě)法,第二種寫(xiě)法被廢棄掉了。第一個(gè)種寫(xiě)法可讀性更好,而且為了程序的兼容性和后期移植的成本,請(qǐng)你也拋棄第二種寫(xiě)法。

raise 'Exception string'

把字符串當(dāng)成異常拋出看上去是一個(gè)非常簡(jiǎn)潔的辦法,但其實(shí)是一個(gè)非常不好的習(xí)慣。

if is_work_done():
   pass
else:
   raise 'Work is not done!' # not cool

上面的語(yǔ)句如果拋出異常,那么會(huì)是這樣的:

Traceback (most recent call last):
 File '/demo/exception_hanlding.py', line 48, in <module>
   raise 'Work is not done!'
TypeError: exceptions must be old-style classes or derived from BaseException, not str

這在Python2.4以前是可以接受的做法,但是沒(méi)有指定異常類型有可能會(huì)讓下游沒(méi)辦法正確捕獲并處理這個(gè)異常,從而導(dǎo)致你的程序掛掉。簡(jiǎn)單說(shuō),這種寫(xiě)法是是封建時(shí)代的陋習(xí),應(yīng)該扔了。

使用內(nèi)置的語(yǔ)法范式代替try/except

Python 本身提供了很多的語(yǔ)法范式簡(jiǎn)化了異常的處理,比如for語(yǔ)句就處理的StopIteration異常,讓你很流暢地寫(xiě)出一個(gè)循環(huán)。

with語(yǔ)句在打開(kāi)文件后會(huì)自動(dòng)調(diào)用finally中的關(guān)閉文件操作。我們?cè)趯?xiě)Python代碼時(shí)應(yīng)該盡量避免在遇到這種情況時(shí)還使用try/except/finally的思維來(lái)處理。

# should not
try:
   f = open(a_file)
   do_something(f)
finally:
   f.close()
# should 
with open(a_file) as f:
   do_something(f)

再比如,當(dāng)我們需要訪問(wèn)一個(gè)不確定的屬性時(shí),有可能你會(huì)寫(xiě)出這樣的代碼:

try:
   test = Test()
   name = test.name  # not sure if we can get its name
except AttributeError:
   name = 'default'

其實(shí)你可以使用更簡(jiǎn)單的getattr()來(lái)達(dá)到你的目的。

name = getattr(test, 'name', 'default')

最佳實(shí)踐

最佳實(shí)踐不限于編程語(yǔ)言,只是一些規(guī)則和填坑后的收獲。

  1. 只處理你知道的異常,避免捕獲所有 異常然后吞掉它們。

  2. 拋出的異常應(yīng)該說(shuō)明原因,有時(shí)候你知道異常類型也猜不出所以然的。

  3. 避免在catch語(yǔ)句塊中干一些沒(méi)意義的事情。

  4. 不要使用異常來(lái)控制流程,那樣你的程序會(huì)無(wú)比難懂和難維護(hù)。

  5. 如果有需要,切記使用finally來(lái)釋放資源。

  6. 如果有需要,請(qǐng)不要忘記在處理異常后做清理工作或者回滾操作。

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Python3 錯(cuò)誤和異常 | 菜鳥(niǎo)教程
一道Python面試題:你真的理解finally了嗎?
python中的異常處理-kouyanghao-ChinaUnix博客
異常用法拓展
python 異常處理和斷言
python except 用法
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服