or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

async-support.mdcallbacks-hooks.mdcore-decorator.mdindex.mdretry-strategies.mdstop-conditions.mdutilities.mdwait-strategies.md
tile.json

tessl/pypi-tenacity

Retry code until it succeeds

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/tenacity@9.1.x

To install, run

npx @tessl/cli install tessl/pypi-tenacity@9.1.0

index.mddocs/

Tenacity - Comprehensive Python Retry Library

Tenacity is a robust Python library that provides decorators and utilities for adding sophisticated retry behavior to functions and code blocks. It offers flexible retry strategies, exponential backoff, customizable stop conditions, and extensive callback mechanisms for both synchronous and asynchronous code.

Package Information

pip install tenacity
import tenacity
from tenacity import retry, stop_after_attempt, wait_exponential

Basic Usage

The simplest way to add retry behavior is with the @retry decorator:

from tenacity import retry, stop_after_attempt, wait_fixed

@retry(stop=stop_after_attempt(3), wait=wait_fixed(1))
def unreliable_function():
    """Function that might fail but will be retried up to 3 times with 1 second between attempts."""
    # Your code here
    pass

Architecture

Tenacity is built around a modular architecture with four core components:

1. Retry Controllers

  • BaseRetrying - Abstract base class for all retry controllers
  • Retrying - Standard synchronous retry controller
  • AsyncRetrying - Asynchronous retry controller for coroutines
  • TornadoRetrying - Tornado web framework integration

2. Retry Strategies

Determine when to retry based on exceptions or return values:

  • Exception-based conditions (retry_if_exception_type, retry_if_exception_message)
  • Result-based conditions (retry_if_result, retry_if_not_result)
  • Logical combinations (retry_any, retry_all)
  • Chain-of-causation support (retry_if_exception_cause_type)

3. Stop Conditions

Control when to stop retrying:

  • Attempt-based (stop_after_attempt)
  • Time-based (stop_after_delay, stop_before_delay)
  • Event-based (stop_when_event_set)
  • Logical combinations (stop_any, stop_all)

4. Wait Strategies

Define delays between retry attempts:

  • Fixed delays (wait_fixed)
  • Exponential backoff (wait_exponential, wait_random_exponential)
  • Random delays (wait_random)
  • Incremental delays (wait_incrementing)
  • Strategy combinations (wait_combine, wait_chain)

Core Type Definitions

from typing import Any, Callable, Union, TypeVar, Optional
from datetime import timedelta
import threading

# Type aliases for time units
time_unit_type = Union[int, float, timedelta]

# Type variables for wrapped functions
WrappedFn = TypeVar('WrappedFn', bound=Callable[..., Any])
WrappedFnReturnT = TypeVar('WrappedFnReturnT')

# Base type aliases for strategy composition
RetryBaseT = Union['retry_base', Callable[['RetryCallState'], bool]]
StopBaseT = Union['stop_base', Callable[['RetryCallState'], bool]]  
WaitBaseT = Union['wait_base', Callable[['RetryCallState'], Union[float, int]]]

# Core state management
class RetryCallState:
    """Tracks state of a retry session."""
    start_time: float
    retry_object: 'BaseRetrying'
    fn: Callable[..., Any]
    args: tuple
    kwargs: dict
    attempt_number: int
    outcome: 'Future'
    outcome_timestamp: Optional[float]
    idle_for: float
    next_action: Optional['BaseAction']
    upcoming_sleep: float
    seconds_since_start: float

class Future:
    """Container for attempt results."""
    attempt_number: int
    failed: bool
    
    @classmethod
    def construct(cls, attempt_number: int, value: Any, has_exception: bool) -> 'Future'

# Exception classes
class TryAgain(Exception):
    """Raise to force immediate retry regardless of retry condition."""
    pass

class RetryError(Exception):
    """Raised when all retry attempts are exhausted."""
    last_attempt: Future
    
    def reraise(self) -> None:
        """Reraise the original exception from the last attempt."""

Main Decorator

def retry(
    sleep: Callable[[float], None] = sleep,
    stop: StopBaseT = stop_never,
    wait: WaitBaseT = wait_none(),
    retry: RetryBaseT = retry_if_exception_type(),
    before: Callable[[RetryCallState], None] = before_nothing,
    after: Callable[[RetryCallState], None] = after_nothing,
    before_sleep: Optional[Callable[[RetryCallState], None]] = None,
    reraise: bool = False,
    retry_error_cls: type = RetryError,
    retry_error_callback: Optional[Callable[[RetryCallState], Any]] = None
) -> Callable[[WrappedFn], WrappedFn]:
    """
    Main decorator to add retry behavior to functions.
    
    Auto-detects async/tornado functions and applies appropriate retry controller.
    
    Parameters:
    - sleep: Function to use for sleeping between retries
    - stop: Strategy determining when to stop retrying
    - wait: Strategy determining how long to wait between retries  
    - retry: Strategy determining whether to retry after a failure
    - before: Callback executed before each attempt
    - after: Callback executed after each attempt
    - before_sleep: Callback executed before sleeping between retries
    - reraise: If True, reraise original exception instead of RetryError
    - retry_error_cls: Exception class to raise when retries are exhausted
    - retry_error_callback: Callback executed when retries are exhausted
    """

Core Capability Areas

Core Decorator & Classes

Complete coverage of the @retry decorator, Retrying, AsyncRetrying, TornadoRetrying classes, and state management components like RetryCallState and Future.

Retry Strategies

All 14+ retry conditions including exception-based (retry_if_exception_type), result-based (retry_if_result), message-based (retry_if_exception_message), and logical combinations (retry_any, retry_all).

Stop Conditions

Complete coverage of 7+ stop strategies including attempt limits (stop_after_attempt), time limits (stop_after_delay, stop_before_delay), event-based stopping, and logical combinations.

Wait Strategies

All 9+ wait/backoff strategies including fixed delays, exponential backoff with jitter, random delays, incremental delays, and strategy composition methods.

Async Support

Comprehensive async/await support with AsyncRetrying, async retry strategies, and integration with asyncio, trio, and other async frameworks.

Callbacks & Hooks

Complete callback system including before/after attempt hooks, before sleep callbacks, logging utilities, and custom callback creation.

Utilities & Helpers

Utility functions, sleep strategies, time conversion helpers, and other supporting functionality for advanced retry scenarios.

Key Features

  • Flexible Retry Logic: 14+ retry strategies based on exceptions, return values, or custom conditions
  • Sophisticated Timing: 9+ wait strategies with exponential backoff, jitter, and custom timing
  • Async/Await Support: Native support for coroutines with AsyncRetrying
  • Framework Integration: Tornado web framework support via TornadoRetrying
  • Comprehensive Callbacks: Before/after/sleep hooks for logging and custom actions
  • Logical Composition: Combine strategies with AND/OR logic
  • Type Safety: Full type annotations and generic support
  • Thread Safety: Built-in threading support with event-based coordination
  • Extensive Configuration: 20+ parameters for fine-tuned retry behavior

Common Patterns

# Exponential backoff with jitter for API calls
@retry(
    stop=stop_after_attempt(5),
    wait=wait_random_exponential(min=1, max=60),
    retry=retry_if_exception_type((ConnectionError, TimeoutError))
)
def call_external_api():
    pass

# Database connection with custom retry logic  
@retry(
    stop=stop_after_delay(30),
    wait=wait_exponential(multiplier=1, min=4, max=10),
    retry=retry_if_exception_type(ConnectionError),
    before_sleep=before_sleep_log(logger, logging.WARNING)
)
def connect_to_database():
    pass

# Async function with comprehensive retry
@retry(
    stop=stop_any(stop_after_attempt(5), stop_after_delay(60)),
    wait=wait_combine(wait_fixed(3), wait_random(0, 2)),
    retry=retry_if_not_result(lambda x: x is not None)
)
async def fetch_data():
    pass

This documentation provides complete coverage of tenacity's 95+ public API elements, enabling robust retry behavior for any Python application.