【Python 軍火庫🧨 - tenacity】升級裝備囉! 讓你寫出來的程式更加的強健

更新於 發佈於 閱讀時間約 8 分鐘
圖片來源

圖片來源

我們開發程式的過程中難免會依賴DB或其他服務, 但複雜的網路環境下我們並沒有辦法確保我們發送的請求是否正確的送達, 因此我們可以在程式中加入Retry機制, 提升我們軟體的強健性。

然而在Python的程式語言裡正好有一個 tenacity 套件非常適合讓我們的Retry作業更加順利, 它是一個兼具彈性及可靠度的Python套件, 除了重試也支援超時機制, 讓我們不在苦於自行實作這些狀況。

這次我們會用個人挑戰為案例來進行生動的演示,讓你不再厭倦學習程式。

給自己一個挑戰

圖片來源

圖片來源

def do_everything():
# 我可以挑戰破關
# 我可以挑戰百岳
# 我還可以...
pass

do_everything()

過程總會發生一些狀況

圖片來源

圖片來源

我們的體力總是有限的, 如果沒有練習的狀況之下去挑戰高強度的百岳很容易體力不夠而無法登頂。

def do_everything():
# 爬山
# 小百岳
# 百岳
# 啊啊啊 遇到瓶頸了
raise Exception('體力有限...爬不動了...')

難道因為一次的體力不夠就此中斷嗎? 那前面的過程會非常可惜, 為了避免這種狀況我們可以…

我們是不是可以來點更可靠的輔助工具

其實爬山這項運動就是不斷的練習、挑戰、檢驗成果, 因此最適合「重試」這個過程, 但我們的重試也應該隨著每次的強度增加休息的時間, 而不是傻傻的爬完立刻重試, 那會沒有什麼效率, 因此我們嘗試導入「tenacity」來解決這個重試的難題, 就像是爬山的過程中增加一些裝備來輔助我們堅持下去一樣。

非常重要的關鍵因子

很重要所以要說三次, @retry、@retry、@retry,這是我們今天的重要主角,它會在我們每一個函式進行補強,透過靈活彈性的裝飾器崁入到我們每一個重要函式,為我們的產品加入一個重要的強鍵性補強。

from tenacity import retry

@retry(...)
def func(...):
...

停損要做好

❌ 基礎: 永遠不要放棄的重試

from tenacity import retry
@retry
def never_gonna_give_you_up():
print("很傻很天真, 重試到頭破血流、天荒地老")
raise Exception

✔️ 適時的停損策略1: 最多N次

from tenacity import retry, stop_after_attempt

@retry(stop=stop_after_attempt(5))
def stop_after_5_attempts():
print("超過5次就掰掰")
raise Exception

✔️ 適時的停損策略2: 不要把時間浪費在沒有結果的努力上

from tenacity import retry, stop_after_delay

@retry(stop=stop_after_delay(30))
def stop_after_30_s():
print("最多給你30秒")
raise Exception

重試之前觀望一下

等個3秒再出發

from tenacity import retry, wait_fixed

@retry(wait=wait_fixed(3))
def wait_3_s():
print("Wait 3 second between retries")
raise Exception

隨機的等待一下

from tenacity import retry, wait_random

@retry(wait=wait_random(min=2, max=4))
def wait_random_2_to_4_s():
print("隨機等個2~4秒再出發")
raise Exception

分佈式服務需要來點…

from tenacity import retry, wait_exponential

@retry(wait=wait_exponential(multiplier=2, min=1, max=10))
def wait_exponential_1():
print("2秒(1*2)、4秒(2*2)、8秒(4*2)...最多不超過10秒")
raise Exception

有條件的進行重試

遇到「什麼條件」的狀況才重試…

from tenacity import retry, retry_if_exception_type, retry_if_not_exception_type

class ClientError(Exception):
"""自訂某些錯誤型態"""

@retry(retry=retry_if_exception_type(IOError))
def io_error():
print("如果是IO類型的錯誤再重試")
raise Exception

@retry(retry=retry_if_not_exception_type(ClientError))
def client_error():
print("如果🚫 不是自訂類型的錯誤再重試")
raise Exception

到達極限了怎麼辦

雖然說努力重試是很棒, 但我們總會遇到極限, 前面我們也提到了即時止損的功能, 但除了即時止損之外, 我們還能做些什麼改變嗎?

from tenacity import retry, stop_after_attempt, retry_error_callback, retry_if_result

def return_last_value(retry_state):
"""return the result of the last call attempt"""
return retry_state.outcome.result()

def is_false(value):
"""Return True if value is False"""
return value is False

# will return False after trying 3 times to get a different result
@retry(stop=stop_after_attempt(3),
retry_error_callback=return_last_value,
retry=retry_if_result(is_false))
def eventually_return_false():
return False

結語

一個具有高品質的產品最重要的就是可靠性,尤其身處數位時代的我們,人人都勢必接觸到我們所開發的軟體,一旦可靠性不佳,輕則影響使用者體驗,重則導致損失,因此身兼軟體開發大任的我們務必要非常的小心,避免造成使用者的損失進而影響到商譽與信用,造成不可挽回的連鎖反應,最後最後,雲產品架構之下最不可控的就是網路(Network)的部分了,為了避免因為網路問題導致系統壞掉,可靠性就顯得格外重要,正好今天這個篇章能夠派上用場,請好好的收藏起來,如果有任何疑問也歡迎留言互相討論,一起加油進步。


您是否苦於網路資訊爆炸嗎? 教學何其多,但卻無法好好選擇的困境呢? 歡迎加入「🔒 阿Han的軟體心法實戰營」, 這裡不給您冗餘的雜訊, 單刀直入直接送您重點, 避開選擇障礙的困境, 讓您獲得業界標準的開發起手式, 成為Top 1的頂尖人才。

avatar-img
118會員
266內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
阿Han的沙龍 的其他內容
這個章節雖然發生問題, 但也很好的為我們如何解決問題的能力而訓練, 我們也會搭配AI來幫我們找問題, 當然也會一五一十的告訴您該如何問對問題, 關於問對問題很重要可以參考「」, 我們相信過程會對大家有幫助, 請耐心閱讀…, 我們會告訴您AI說正確但事實上並非正確的情境。 我們在「【🔒 Pytho
我們在「【資料處理神器區 - Pytube系列】 蒐集情報讓數據會說話」有介紹怎麼分析Youtube影音資訊,但過程中卻遇到了一些問題...,沒關係,動動手做個Maker來解決麻煩吧! 前景提要 故事是這樣的, 小明在使用pytube進行Youtube頻道的分析時, 發現到奇怪, 原本抓影片可以
我們在「【Python 軍火庫 - PySubs2】 字幕檔提取工具的好幫手(ass、ssa、srt、vtt…)」有稍微跟大家介紹了字幕檔處理工具的基本用法,相信對於讀取字幕,更改文字內容應該是再容易不過的事了,咦…,但我們好像都沒有看到關於新增「段落」的資訊耶,不曉得是我沒有仔細尋找還是真的沒
我們在「」有稍微介紹了JSON格式, 也知曉JSON格式非常簡單暴力, 只要一對<key>與<value>就能成行, 對於工程人員來說已經比XML、文字檔…等傳統格式更加容易理解, 而且也具備一定的資料型態基礎, 但使用這麼久以來常常發現到想要對某個欄位註解時好像不太容易, 頂多就是多一個欄位叫做「
JSON 全名 JavaScript Object Notation,其格式基本上就是key: value的組成如下: { "name": "Bob", "age": 40, "childs": [ { "name": "Justin", "
請耐心閱讀到最後, 我們會提供更優雅的方式來處理這項需求… 故事起源 我們常常在使用Python的過程中會進行I/O的一些處理, 那麼最基本的就會是讀取檔案列表並對每一個特定的檔案名稱進行處理, 像這樣: import glob mp4_files = glob.glob(os.path
這個章節雖然發生問題, 但也很好的為我們如何解決問題的能力而訓練, 我們也會搭配AI來幫我們找問題, 當然也會一五一十的告訴您該如何問對問題, 關於問對問題很重要可以參考「」, 我們相信過程會對大家有幫助, 請耐心閱讀…, 我們會告訴您AI說正確但事實上並非正確的情境。 我們在「【🔒 Pytho
我們在「【資料處理神器區 - Pytube系列】 蒐集情報讓數據會說話」有介紹怎麼分析Youtube影音資訊,但過程中卻遇到了一些問題...,沒關係,動動手做個Maker來解決麻煩吧! 前景提要 故事是這樣的, 小明在使用pytube進行Youtube頻道的分析時, 發現到奇怪, 原本抓影片可以
我們在「【Python 軍火庫 - PySubs2】 字幕檔提取工具的好幫手(ass、ssa、srt、vtt…)」有稍微跟大家介紹了字幕檔處理工具的基本用法,相信對於讀取字幕,更改文字內容應該是再容易不過的事了,咦…,但我們好像都沒有看到關於新增「段落」的資訊耶,不曉得是我沒有仔細尋找還是真的沒
我們在「」有稍微介紹了JSON格式, 也知曉JSON格式非常簡單暴力, 只要一對<key>與<value>就能成行, 對於工程人員來說已經比XML、文字檔…等傳統格式更加容易理解, 而且也具備一定的資料型態基礎, 但使用這麼久以來常常發現到想要對某個欄位註解時好像不太容易, 頂多就是多一個欄位叫做「
JSON 全名 JavaScript Object Notation,其格式基本上就是key: value的組成如下: { "name": "Bob", "age": 40, "childs": [ { "name": "Justin", "
請耐心閱讀到最後, 我們會提供更優雅的方式來處理這項需求… 故事起源 我們常常在使用Python的過程中會進行I/O的一些處理, 那麼最基本的就會是讀取檔案列表並對每一個特定的檔案名稱進行處理, 像這樣: import glob mp4_files = glob.glob(os.path
你可能也想看
Google News 追蹤
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
從範例學python的目標讀者: 針對剛進入的初學者,想學習Python語言。 有基礎本數學邏輯基礎即可。 從小遊戲學python的目標讀者: 針對已經有經驗的C/C++, Python, 或其他有程式基礎的讀者。 想實作一些小專案,從實做中學習如何分析需求、元件分拆、到底層實作
Thumbnail
過程中要攻克的高山,不只一座:有環境、時運,還有自己。 那總是打不破的天花板,還有不得不的止步與數不盡的挫敗,嚐起來有多苦!
Thumbnail
生命中充滿了挑戰和困難 我們常常會在面對重重阻礙時感到力不從心,想要放棄。但是,我們要明白,只要堅持下去,就一定能夠戰勝困難,實現自己的目標。失敗了再爬起來,才是真正的勇敢!這句話簡單明瞭,卻蘊含著無限的力量。人生不如意十之八九,我們每個人都會在生活的道路上遇到挫折與困難。然而,真正能夠在困境
Thumbnail
「那看起來好好玩喔!」。圓形號召其他各種形狀們一起來造一座屬於自己的高塔。
在所有的力量中,最重要的特質就是勇氣和意志力。這兩項特質是人類面對困難、不屈不撓的重要支柱。勇氣不是不感到恐懼,而是在恐懼面前仍能堅持正確的行動。意志力則是在誘惑和挑戰面前保持堅定,不讓外界影響到自己的決定和行為。 想像一個攀登高峰的登山者,他面對嚴峻的自然條件和體力的極限,但他的內心充滿了征
當生活中遇到挑戰和難題時,我們該怎麼辦呢?讓我們來聊聊在困境中堅持、順風順水時又該怎麼辦。 面對困境,堅持不懈 在生活中,時不時就會碰上各種挑戰和難題,對吧?這時候,該怎麼辦才好呢?困境,嘖嘖,真不是鬧著玩的。有時候會讓人感到力不從心,差點就想要放棄了。但你知道嗎?堅持下去其實是一種超級重要的技
Thumbnail
我想這是無數次爬山帶給我的禮物,所謂的「到達」是在心裡畫一個圓,從天真的勇敢裡出發,在所有複雜裡走了一圈,回到最初的地方,帶著圓滿的單純,繼續下一段旅程。
Thumbnail
參加Leetcode的30 Days of Pandas挑戰,除了是學習的機會,更是練習熟悉pandas功能的機會。文章分享了挑戰簡介、題目描述、關鍵技術以及參加挑戰的心得。適合新手學習pandas,也可提升熟練度。
Thumbnail
本文介紹Python程式設計中處理異常的try, except, else, finally語句,並提供程式範例來更深刻理解使用方法。
Thumbnail
無論是天分還是努力,都不是唯一的成就條件,真正關鍵在於持久的熱情和堅持不懈的毅力。而這種品質與天賦不同,是可以透過自己的努力和刻意練習來培養的。《恆毅力:人生成功的究極能力》提供了實用的方法,教導讀者如何培養和強化恆毅力,這將對個人和職業生涯的發展產生積極的影響,使你更有信心和動力去追求自己的目標。
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
從範例學python的目標讀者: 針對剛進入的初學者,想學習Python語言。 有基礎本數學邏輯基礎即可。 從小遊戲學python的目標讀者: 針對已經有經驗的C/C++, Python, 或其他有程式基礎的讀者。 想實作一些小專案,從實做中學習如何分析需求、元件分拆、到底層實作
Thumbnail
過程中要攻克的高山,不只一座:有環境、時運,還有自己。 那總是打不破的天花板,還有不得不的止步與數不盡的挫敗,嚐起來有多苦!
Thumbnail
生命中充滿了挑戰和困難 我們常常會在面對重重阻礙時感到力不從心,想要放棄。但是,我們要明白,只要堅持下去,就一定能夠戰勝困難,實現自己的目標。失敗了再爬起來,才是真正的勇敢!這句話簡單明瞭,卻蘊含著無限的力量。人生不如意十之八九,我們每個人都會在生活的道路上遇到挫折與困難。然而,真正能夠在困境
Thumbnail
「那看起來好好玩喔!」。圓形號召其他各種形狀們一起來造一座屬於自己的高塔。
在所有的力量中,最重要的特質就是勇氣和意志力。這兩項特質是人類面對困難、不屈不撓的重要支柱。勇氣不是不感到恐懼,而是在恐懼面前仍能堅持正確的行動。意志力則是在誘惑和挑戰面前保持堅定,不讓外界影響到自己的決定和行為。 想像一個攀登高峰的登山者,他面對嚴峻的自然條件和體力的極限,但他的內心充滿了征
當生活中遇到挑戰和難題時,我們該怎麼辦呢?讓我們來聊聊在困境中堅持、順風順水時又該怎麼辦。 面對困境,堅持不懈 在生活中,時不時就會碰上各種挑戰和難題,對吧?這時候,該怎麼辦才好呢?困境,嘖嘖,真不是鬧著玩的。有時候會讓人感到力不從心,差點就想要放棄了。但你知道嗎?堅持下去其實是一種超級重要的技
Thumbnail
我想這是無數次爬山帶給我的禮物,所謂的「到達」是在心裡畫一個圓,從天真的勇敢裡出發,在所有複雜裡走了一圈,回到最初的地方,帶著圓滿的單純,繼續下一段旅程。
Thumbnail
參加Leetcode的30 Days of Pandas挑戰,除了是學習的機會,更是練習熟悉pandas功能的機會。文章分享了挑戰簡介、題目描述、關鍵技術以及參加挑戰的心得。適合新手學習pandas,也可提升熟練度。
Thumbnail
本文介紹Python程式設計中處理異常的try, except, else, finally語句,並提供程式範例來更深刻理解使用方法。
Thumbnail
無論是天分還是努力,都不是唯一的成就條件,真正關鍵在於持久的熱情和堅持不懈的毅力。而這種品質與天賦不同,是可以透過自己的努力和刻意練習來培養的。《恆毅力:人生成功的究極能力》提供了實用的方法,教導讀者如何培養和強化恆毅力,這將對個人和職業生涯的發展產生積極的影響,使你更有信心和動力去追求自己的目標。