【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
留言分享你的想法!
avatar-img
阿Han的沙龍
131會員
289內容數
哈囉,我是阿Han,是一位 👩‍💻 軟體研發工程師,喜歡閱讀、學習、撰寫文章及教學,擅長以圖代文,化繁為簡,除了幫助自己釐清思路之外,也希望藉由圖解的方式幫助大家共同學習,甚至手把手帶您設計出高品質的軟體產品。
阿Han的沙龍的其他內容
2025/01/29
🤔 簡單且靜態就足夠了? 相信我們在開發Python應用程式的過程中, 常常會借用Enum來定義我們可能的選項, 就像顏色紅、綠、黃會有這樣的結構: class Color(str, Enum): RED = 'red' GREED = 'green' YELLOW = 'yel
Thumbnail
2025/01/29
🤔 簡單且靜態就足夠了? 相信我們在開發Python應用程式的過程中, 常常會借用Enum來定義我們可能的選項, 就像顏色紅、綠、黃會有這樣的結構: class Color(str, Enum): RED = 'red' GREED = 'green' YELLOW = 'yel
Thumbnail
2025/01/08
當我們的系統發展到一定程度時, 難免會面臨到正式上線的問題, 要如何讓維運更加簡易呢? 尤其隨著複雜的客製化配置的出現時, 我們應該如何有效的管理, 甚至驗證配置是否如預期資料型態、格式…, 而正好 pydantic 可以滿足這樣的需求, 就讓我們來看看怎麼使用吧! 需安裝的套件 pip i
Thumbnail
2025/01/08
當我們的系統發展到一定程度時, 難免會面臨到正式上線的問題, 要如何讓維運更加簡易呢? 尤其隨著複雜的客製化配置的出現時, 我們應該如何有效的管理, 甚至驗證配置是否如預期資料型態、格式…, 而正好 pydantic 可以滿足這樣的需求, 就讓我們來看看怎麼使用吧! 需安裝的套件 pip i
Thumbnail
2025/01/02
要如何使用unicorn啟動多個FastAPI服務, 歡迎參考我們的「【💊 Python的解憂錦囊 - FastAPI】如何啟動多個Workers」。 當我們試著設計帶入模組化時… 我們在「【💊 Python的解憂錦囊 - FastAPI】使用 lifespan 來共享資料與管理生命週期
Thumbnail
2025/01/02
要如何使用unicorn啟動多個FastAPI服務, 歡迎參考我們的「【💊 Python的解憂錦囊 - FastAPI】如何啟動多個Workers」。 當我們試著設計帶入模組化時… 我們在「【💊 Python的解憂錦囊 - FastAPI】使用 lifespan 來共享資料與管理生命週期
Thumbnail
看更多
你可能也想看
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
全球科技產業的焦點,AKA 全村的希望 NVIDIA,於五月底正式發布了他們在今年 2025 第一季的財報 (輝達內部財務年度為 2026 Q1,實際日曆期間為今年二到四月),交出了打敗了市場預期的成績單。然而,在銷售持續高速成長的同時,川普政府加大對於中國的晶片管制......
Thumbnail
全球科技產業的焦點,AKA 全村的希望 NVIDIA,於五月底正式發布了他們在今年 2025 第一季的財報 (輝達內部財務年度為 2026 Q1,實際日曆期間為今年二到四月),交出了打敗了市場預期的成績單。然而,在銷售持續高速成長的同時,川普政府加大對於中國的晶片管制......
Thumbnail
耐心,不僅僅是咬牙堅持的結果,更是因為我們能夠看得更遠。這就像計劃一次長途旅行:我們知道路上會有挑戰,但也滿心期待到達終點時的美景。一旦我們意識到這一點,就能在等待中保持耐心。
Thumbnail
耐心,不僅僅是咬牙堅持的結果,更是因為我們能夠看得更遠。這就像計劃一次長途旅行:我們知道路上會有挑戰,但也滿心期待到達終點時的美景。一旦我們意識到這一點,就能在等待中保持耐心。
Thumbnail
前陣子與朋友們到南勢角爬山, 解鎖了人生中第一個小百岳, 而我也在這13公里的挑戰中, 體會了許多箇中滋味。 爬山也可以是自我對話與覺察的機會。
Thumbnail
前陣子與朋友們到南勢角爬山, 解鎖了人生中第一個小百岳, 而我也在這13公里的挑戰中, 體會了許多箇中滋味。 爬山也可以是自我對話與覺察的機會。
Thumbnail
歡迎支持與學習,讓阿Han幫您脫離無限加班的惡性循環… 您是否苦於網路資訊爆炸嗎? 教學何其多,但卻無法好好選擇的困境呢? 歡迎加入實戰營, 這裡不給您冗餘的雜訊, 單刀直入直接送您重點, 避開選擇障礙的困境, 讓您獲得業界標準的開發起手式, 成為Top 1的頂尖人才。
Thumbnail
歡迎支持與學習,讓阿Han幫您脫離無限加班的惡性循環… 您是否苦於網路資訊爆炸嗎? 教學何其多,但卻無法好好選擇的困境呢? 歡迎加入實戰營, 這裡不給您冗餘的雜訊, 單刀直入直接送您重點, 避開選擇障礙的困境, 讓您獲得業界標準的開發起手式, 成為Top 1的頂尖人才。
Thumbnail
學習軟體開發的路上常常苦於網路資訊爆炸嗎? 教學何其多,但卻遇到無法明確選擇的困境呢? 歡迎加入「🔒 阿Han的軟體心法實戰營」, 這裡不給您冗餘的雜訊, 單刀直入直接送您業界開發重點, 避開選擇障礙的困境, 讓您獲得業界標準的開發起手式, 成為Top 1的頂尖人才。 人生的道路中總會來點意外與
Thumbnail
學習軟體開發的路上常常苦於網路資訊爆炸嗎? 教學何其多,但卻遇到無法明確選擇的困境呢? 歡迎加入「🔒 阿Han的軟體心法實戰營」, 這裡不給您冗餘的雜訊, 單刀直入直接送您業界開發重點, 避開選擇障礙的困境, 讓您獲得業界標準的開發起手式, 成為Top 1的頂尖人才。 人生的道路中總會來點意外與
Thumbnail
我們開發程式的過程中難免會依賴DB或其他服務, 但複雜的網路環境下我們並沒有辦法確保我們發送的請求是否正確的送達, 因此我們可以在程式中加入Retry機制, 提升我們軟體的強健性。 然而在Python的程式語言裡正好有一個 tenacity 套件非常適合讓我們的Retry作業更加順利, 它是一
Thumbnail
我們開發程式的過程中難免會依賴DB或其他服務, 但複雜的網路環境下我們並沒有辦法確保我們發送的請求是否正確的送達, 因此我們可以在程式中加入Retry機制, 提升我們軟體的強健性。 然而在Python的程式語言裡正好有一個 tenacity 套件非常適合讓我們的Retry作業更加順利, 它是一
Thumbnail
「堅強」兩個字,對你而言,是什麼樣的意象呢? 是能夠承受巨大的苦痛的意志力?是能撐過千百次磨練的毅力?還是泰山崩於前也面不改色的鎮定? 我們常常在遭到挫折打擊,或表現出軟弱的時候,聽到有人說:「你要堅強一點。」 說得像是我們可以自由掌控心理,對痛苦減敏,在恐懼面前裝淡定,這樣是合理,是可行的嗎?真的
Thumbnail
「堅強」兩個字,對你而言,是什麼樣的意象呢? 是能夠承受巨大的苦痛的意志力?是能撐過千百次磨練的毅力?還是泰山崩於前也面不改色的鎮定? 我們常常在遭到挫折打擊,或表現出軟弱的時候,聽到有人說:「你要堅強一點。」 說得像是我們可以自由掌控心理,對痛苦減敏,在恐懼面前裝淡定,這樣是合理,是可行的嗎?真的
Thumbnail
我說,你像個征服百岳的登山客,沿路撿拾彷彿有用的東西放進你的大背包,它越來越重,你的身體越來越累、越垮…可你的眼睛盯著前面百岳說「還沒,我還不夠…」繼續鞭策自己,無視已受傷的身心
Thumbnail
我說,你像個征服百岳的登山客,沿路撿拾彷彿有用的東西放進你的大背包,它越來越重,你的身體越來越累、越垮…可你的眼睛盯著前面百岳說「還沒,我還不夠…」繼續鞭策自己,無視已受傷的身心
Thumbnail
這幾天和朋友聊天,他們說我好酷,經歷那麼多冒險!我脫口而出,那是因為我實在太弱了,所以製造了那麼多冒險。如果我夠強壯,我不會爬山爬得那麼辛苦、不會墜崖、不會騎單車上不了坡、不會划海洋獨木舟不斷被海浪打回來、不會爬到高空邊哭邊走、不會當先鋒攀登者當到手腳擦傷...。 因為我太弱了,所以每次戶外體驗活動
Thumbnail
這幾天和朋友聊天,他們說我好酷,經歷那麼多冒險!我脫口而出,那是因為我實在太弱了,所以製造了那麼多冒險。如果我夠強壯,我不會爬山爬得那麼辛苦、不會墜崖、不會騎單車上不了坡、不會划海洋獨木舟不斷被海浪打回來、不會爬到高空邊哭邊走、不會當先鋒攀登者當到手腳擦傷...。 因為我太弱了,所以每次戶外體驗活動
Thumbnail
「恆毅力Grit」讀後精華節選分享~
Thumbnail
「恆毅力Grit」讀後精華節選分享~
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News