99热99这里只有精品6国产,亚洲中文字幕在线天天更新,在线观看亚洲精品国产福利片 ,久久久久综合网

歡迎加入QQ討論群258996829
麥子學(xué)院 頭像
蘋果6袋
6
麥子學(xué)院

Python中異常處理方法步驟詳解

發(fā)布時(shí)間:2016-12-20 21:09  回復(fù):0  查看:2706   最后回復(fù):2016-12-20 21:09  

異常處理在任何一門編程語言里都是值得關(guān)注的一個(gè)話題,良好的異常處理可以讓你的程序更加健壯,清晰的錯(cuò)誤信息更能幫助你快速修復(fù)問題。在Python開發(fā)中,和部分高級(jí)語言一樣,使用了try/except/finally語句塊來處理異常,如果你有其他編程語言的經(jīng)驗(yàn),實(shí)踐起來并不難。

  異常處理語句 try…excpet…finally

  實(shí)例代碼

  defdiv(ab):

  try:

  print(a / b)

  exceptZeroDivisionError:

  print("Error: b should not be 0 !!")

  exceptExceptionas 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 linetry:

  print(a / b)

  except (ZeroDivisionError, TypeError) as e:

  print(e)

  # Except block is optional when there is finallytry:

  open(database)finally:

  close(database)

  catch all errors and log ittry:

  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 語句不是必須的, finally 語句也不是必須的,但是二者必須要有一個(gè),否則就沒有 try 的意義了。

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

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

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

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

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

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

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

  拋出異常 raise

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

  raiseNameError("bad name!")

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

  importexceptions

  # ['ArithmeticError', 'AssertionError'.....]

  printdir(exceptions)

  自定義異常類型

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

  class SomeCustomException(Exception):

  pass

  一般你在自定義異常類型時(shí),需要考慮的問題應(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 語句即可:

  deff1():

  print(1/0)

  deff2():

  try:

  f1()

  exceptExceptionas e:

  raise # don't raise e !!!

  f2()

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

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

  deff2():

  try:

  f1()

  exceptExceptionas e:

  e.args += ('more info',)

  raise

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

  Exception 和 BaseException

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

  BaseException

  +-- SystemExit

  +-- KeyboardInterrupt

  +-- GeneratorExit

  +-- Exception

  +-- StopIteration...

  +-- StandardError...

  +-- Warning...

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

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

  except Exception as e和 except Exception, e

  代碼示例如下:

  try:

  do_something()

  exceptNameErroras e: # should

  pass

  exceptKeyError, e: # should not

  pass

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

  raise “Exception string”

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

  if is_work_done():

  passelse:

  raise "Work is not done!" # not cool

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

  Traceback (mostrecentcalllast):

  File "/demo/exception_hanlding.py", line 48, in

  raise "Work is not done!"

  TypeError: exceptionsmustbeold-styleclassesor derivedfromBaseException, not str

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

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

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

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

  # should nottry:

  f = open(a_file)

  do_something(f)finally:

  f.close()

  # should

  withopen(a_file) as f:

  do_something(f)

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

  try:

  test = Test()

  name = test.name # not sure if we can get its name

  exceptAttributeError:

  name = 'default'

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

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

  最佳實(shí)踐

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

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

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

  3. 避免在catch語句塊中干一些沒意義的事情。

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

  5. 如果有需要,切記使用finally來釋放資源。

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


來源:伯樂在線

您還未登錄,請(qǐng)先登錄

熱門帖子

最新帖子

?