中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

try...finally如何在python項目中使用

發布時間:2020-11-25 14:16:19 來源:億速云 閱讀:135 作者:Leah 欄目:開發技術

try...finally如何在python項目中使用 ?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。

1. 關于 try.. finally..

假如上帝用 python 為每一個來到世界的生物編寫程序,那么除去中間過程的種種復雜實現,最不可避免的就是要保證每個實例最后都要掛掉。代碼可簡寫如下:

try:
  born() # 出生

  # 正常降臨世界
  # do something..

except ValueError:
  # 安排錯誤
  # do something...

except AttributeError:
  # 特征錯誤
  # do something...

except TypeError:
  # 種類錯誤
  # do something...

... # 等等雜七雜八的錯誤

finally:
  go_die() # 掛掉
  come_to_see_me() # 然后來見我
  reincarnate() # 下一輪,安排!

這就是 finally 的作用和實例。就算捕獲異常后再次出現異常,最終也能保證 go_die 方法會執行,但是,如果 go_die 方法出現錯誤,那么就不能正常去見上帝了。為了保證每個生物(不管有沒有掛掉)都能見到上帝他老人家,并開始下一個輪回(不管有沒有見到),需要做如下處理:

...

finally:
  try:
    go_die()
  finally:
    try:
      come_to_see_me()
    finally:
      reincarnate()

OK,功能雖然實現了,但按照 The Zen of Python 所說:Flat is better than nested.(扁平優于嵌套),那么這段代碼就略顯丑陋了。為了遵循 python 美學,我們可以對這段進行優化,使它看起來更為美觀。

2. 錯誤的上下文:__context__

在此之前,需要引入一個新的概念: __context____context__ 的字面意思就是上下文,它屬于錯誤的一個屬性。在錯誤捕獲中,它意味著當你處理一個錯誤時,另一個錯誤發生了。也就是說,你所捕獲的錯誤雖然被成功捕獲了,但當捕獲完成時,你的一些操作導致另一個錯誤發生,而這個錯誤并沒有被捕獲。通常情況下,如果處理的好,那么當前錯誤的 __context__ 的值為 None,如果處理不好那就是你所捕獲的錯誤。比如下面的代碼:

def type_err():
  raise TypeError('this is a type error.')

def after_type_err():
  raise ValueError('this is a value error.')

try:
  type_err()
except TypeError:
  after_type_err()

執行結果為:

Traceback (most recent call last):
 File "<ipython-input-4-189a22d65266>", line 8, in <module>
  type_err()
 File "<ipython-input-4-189a22d65266>", line 2, in type_err
  raise TypeError('this is a type error.')
TypeError: this is a type error.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
 File "C:\Users\lineu\AppData\Local\Programs\Python\Python37\lib\site-packages\IPython\core\interactiveshell.py", line 3326, in run_code
  exec(code_obj, self.user_global_ns, self.user_ns)
 File "<ipython-input-4-189a22d65266>", line 10, in <module>
  after_type_err()
 File "<ipython-input-4-189a22d65266>", line 5, in after_type_err
  raise ValueError('this is a value error.')
ValueError: this is a value error.

在上面的錯誤信息中,當前錯誤類型為 ValueError,它的 __context__ 屬性值為 TypeError 實例,而 TypeError 實例的 __context__None

3. FinalExecutor:優雅的 finally

有了 __context__ 的概念,我們就可以基于此實現一個優雅的“輪回”了。基本思路為:依次執行方法,如果方法報錯,那么就將該錯誤的 __context__ 值設置為上一個錯誤(如果有)。最后等到所有方法執行完畢,再拋出最后一個錯誤,那么此時的錯誤將包含所有可能被引發的錯誤信息。具體代碼如下:

class FinalExecutor(object):
  """終極執行器
  用于確保你所有的方法都會被執行(不管中途有沒有方法報錯)
  同時能看到正確的錯誤信息
  """

  def __init__(self):
    self.last_err = None # 保存最近發生的錯誤

  def __enter__(self):
    return self

  def __exit__(self, exc_type, exc_val, exc_tb):
    # 如果有發生錯誤,則拋出
    if self.last_err:
      raise self.last_err

  def call(self, func, *args, **kwargs):
    """調用執行方法"""
    try:
      func(*args, **kwargs)
    except Exception as e:
      # Exception 捕獲所有繼承自它或它子類的錯誤類型
      # 捕獲它等于捕獲幾乎所有錯誤

      if self.last_err:
        # 將本次錯誤的上下文定義為上一次錯誤
        e.__context__ = self.last_err

      # 更新為當前錯誤
      self.last_err = e

我們的終極執行器使用示例為:

# 定義 3 個方法用于測試
def type_err():
  print('type error')
  raise TypeError('x')


def value_err():
  print('value error')
  raise ValueError('x')


def attr_err():
  print('attr error')
  raise AttributeError('x')


# 使用 with 語句來啟動終極執行器
with FinalExecutor() as e:
  e.call(type_err)
  e.call(value_err)
  e.call(attr_err)

運行可以看到方法最終都被執行了,且錯誤信息一個不漏:

type error
value error
attr error
Traceback (most recent call last):
 File "<ipython-input-5-1b07c576630b>", line 19, in call
  func(*args, **kwargs)
 File "<ipython-input-6-d602d89ed0e7>", line 3, in type_err
  raise TypeError('x')
TypeError: x

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
 File "<ipython-input-5-1b07c576630b>", line 19, in call
  func(*args, **kwargs)
 File "<ipython-input-6-d602d89ed0e7>", line 8, in value_err
  raise ValueError('x')
ValueError: x

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
 File "C:\Users\lineu\AppData\Local\Programs\Python\Python37\lib\site-packages\IPython\core\interactiveshell.py", line 3326, in run_code
  exec(code_obj, self.user_global_ns, self.user_ns)
 File "<ipython-input-6-d602d89ed0e7>", line 19, in <module>
  e.call(attr_err)
 File "<ipython-input-5-1b07c576630b>", line 15, in __exit__
  raise self.last_err
 File "<ipython-input-5-1b07c576630b>", line 19, in call
  func(*args, **kwargs)
 File "<ipython-input-6-d602d89ed0e7>", line 13, in attr_err
  raise AttributeError('x')
AttributeError: x

4. 使用 ExitStack

有了我們的終極執行器,上帝就可以優雅的寫代碼了。為了讓每個人都能這樣優雅的寫 python 代碼,python 為我們提供了一個封裝好的功能,當然它的實現要比我們的終極執行器復雜一些(考慮的也更周到一些~)。我們可以通過 contextlib 模塊導入該方法并使用:

from contextlib import ExitStack


with ExitStack() as stack:
  stack.callback(type_err)
  stack.callback(value_err)
  stack.callback(attr_err)

注意該 ExitStackFinalExecutor 不同的是,它是倒序執行的。

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

清镇市| 宜良县| 增城市| 读书| 惠来县| 沂源县| 岐山县| 板桥市| 平邑县| 宁国市| 琼中| 衡山县| 大丰市| 旬阳县| 凤庆县| 杨浦区| 舟曲县| 罗源县| 新余市| 新平| 邯郸市| 泗水县| 甘孜县| 城步| 巴楚县| 三门县| 沈阳市| 含山县| 蓬莱市| 林口县| 正阳县| 惠安县| 图们市| 郸城县| 交口县| 宁都县| 彰化县| 谢通门县| 泸州市| 常熟市| 若羌县|