Mastering Elegant Retry Logic in Python with Tenacity
This article explains why retry mechanisms are essential for unstable network requests, introduces the Tenacity library, and provides clear, step‑by‑step Python examples covering basic retries, stop conditions, conditional retries, exception re‑raising, and callback handling.
Network instability often causes request timeouts, making retry logic crucial for robust applications.
The third‑party library Tenacity offers a comprehensive solution for implementing retries in Python, handling scenarios such as when to retry, how many attempts, delay intervals, and post‑failure callbacks.
When should a retry be performed?
How many times to retry?
When to stop retrying?
What interval between retries?
Callback after retry failure?
Install Tenacity via pip:
$ pip install tenacity1. Basic Unconditional Retry
Retry without any condition and without delay:
from tenacity import retry
@retry
def test_retry():
print("Waiting for retry, no interval...")
raise Exception
test_retry()Retry with a fixed 2‑second wait before each attempt:
from tenacity import retry, wait_fixed
@retry(wait=wait_fixed(2))
def test_retry():
print("Waiting for retry...")
raise Exception
test_retry()2. Setting Stop Conditions
Stop after a maximum number of attempts (e.g., 7):
from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(7))
def test_retry():
print("Waiting for retry...")
raise Exception
test_retry()Stop after a time limit (e.g., 10 seconds):
from tenacity import retry, stop_after_delay
@retry(stop=stop_after_delay(10))
def test_retry():
print("Waiting for retry...")
raise Exception
test_retry()Combine both conditions (stop when either is met):
from tenacity import retry, stop_after_delay, stop_after_attempt
@retry(stop=(stop_after_delay(10) | stop_after_attempt(7)))
def test_retry():
print("Waiting for retry...")
raise Exception
test_retry()3. Conditional Retry Triggers
Retry only on specific exceptions, such as request timeouts:
from requests import exceptions
from tenacity import retry, retry_if_exception_type
@retry(retry=retry_if_exception_type(exceptions.Timeout))
def test_retry():
print("Waiting for retry...")
raise exceptions.Timeout
test_retry()Retry based on a custom result condition (e.g., function returns False):
from tenacity import retry, stop_after_attempt, retry_if_result
def is_false(value):
return value is False
@retry(stop=stop_after_attempt(3), retry=retry_if_result(is_false))
def test_retry():
return False
print(test_retry())4. Reraising the Original Exception
By default Tenacity raises RetryError after exhausting retries; use reraise=True to propagate the original exception:
from tenacity import retry, stop_after_attempt
@retry(stop=stop_after_attempt(7), reraise=True)
def test_retry():
print("Waiting for retry...")
raise Exception
test_retry()5. Adding a Callback After Final Failure
Execute a callback function when all retries fail, optionally returning the original result:
from tenacity import *
def return_last_value(retry_state):
print("Executing callback")
return retry_state.outcome.result()
def is_false(value):
return value is False
@retry(stop=stop_after_attempt(3), retry_error_callback=return_last_value, retry=retry_if_result(is_false))
def test_retry():
print("Waiting for retry...")
return False
print(test_retry())Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Python Crawling & Data Mining
Life's short, I code in Python. This channel shares Python web crawling, data mining, analysis, processing, visualization, automated testing, DevOps, big data, AI, cloud computing, machine learning tools, resources, news, technical articles, tutorial videos and learning materials. Join us!
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
