or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/pypi-timeout-decorator

Timeout decorator for Python functions with signal-based and multiprocessing timeout strategies

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/timeout-decorator@0.5.x

To install, run

npx @tessl/cli install tessl/pypi-timeout-decorator@0.5.0

index.mddocs/

Timeout Decorator

A Python decorator that enables developers to set execution timeouts for functions, preventing them from running indefinitely. It offers two timeout strategies: signal-based timeouts for main thread execution and multiprocessing-based timeouts for worker threads or web application contexts where signals are not available.

Package Information

  • Package Name: timeout-decorator
  • Package Type: pypi
  • Language: Python
  • Installation: pip install timeout-decorator

Core Imports

from timeout_decorator import timeout, TimeoutError

Alternative import pattern:

import timeout_decorator

# Use as timeout_decorator.timeout(5)

Basic Usage

import time
from timeout_decorator import timeout, TimeoutError

# Basic timeout with default settings (signal-based)
@timeout(5)
def slow_function():
    print("Start")
    for i in range(1, 10):
        time.sleep(1)
        print(f"{i} seconds have passed")

# This will raise TimeoutError after 5 seconds
try:
    slow_function()
except TimeoutError:
    print("Function timed out!")

# Multiprocessing-based timeout for thread-safe contexts
@timeout(3, use_signals=False)
def worker_function():
    time.sleep(5)  # This will timeout

try:
    worker_function()
except TimeoutError:
    print("Worker function timed out!")

Architecture

The timeout decorator provides two distinct timeout strategies to accommodate different execution contexts:

Signal-based Strategy (Default)

  • Mechanism: Uses signal.SIGALRM to interrupt function execution
  • Context: Only works in the main thread of the process
  • Precision: Provides precise timeout control down to microseconds
  • Performance: Minimal overhead, direct signal handling
  • Use Cases: Single-threaded applications, command-line tools, standalone scripts

Multiprocessing Strategy

  • Mechanism: Spawns a separate process to execute the function with timeout monitoring
  • Context: Works in any thread or execution environment (main thread, worker threads, web applications)
  • Precision: Limited to 0.01-second (10ms) granularity due to polling mechanism
  • Performance: Higher overhead due to process creation and inter-process communication
  • Requirements: Function arguments and return values must be pickle-serializable
  • Use Cases: Web applications, multi-threaded applications, any context where signals are not available

The decorator automatically handles strategy selection based on the use_signals parameter, allowing developers to choose the appropriate timeout mechanism for their specific execution context.

Capabilities

Timeout Decorator

The main decorator function that adds timeout functionality to any function. Supports both signal-based and multiprocessing-based timeout strategies with configurable exception handling.

def timeout(seconds=None, use_signals=True, timeout_exception=TimeoutError, exception_message=None):
    """
    Add a timeout parameter to a function and return it.

    Parameters:
    - seconds (float, optional): Time limit in seconds or fractions of a second. 
      If None is passed, no timeout is applied. This adds flexibility to usage: 
      you can disable timing out depending on settings.
    - use_signals (bool, default=True): Flag indicating whether signals should be 
      used for timing function out or multiprocessing. When using multiprocessing, 
      timeout granularity is limited to 10ths of a second.
    - timeout_exception (Exception, default=TimeoutError): Custom exception type 
      to raise on timeout.
    - exception_message (str, optional): Custom message for the timeout exception.

    Returns:
    Decorated function with timeout capability

    Raises:
    TimeoutError (or custom exception) if time limit is reached
    """

Usage Examples

Basic timeout with seconds:

@timeout(5)
def my_function():
    # Function implementation
    pass

Fractional seconds:

@timeout(0.5)
def quick_function():
    # Must complete within half a second
    pass

Custom exception type:

@timeout(5, timeout_exception=RuntimeError)
def my_function():
    # Will raise RuntimeError instead of TimeoutError
    pass

Custom exception message:

@timeout(5, exception_message="Operation took too long")
def my_function():
    # Will raise TimeoutError with custom message
    pass

Multiprocessing strategy (thread-safe):

@timeout(5, use_signals=False)
def thread_worker():
    # Safe to use in threads or web applications
    pass

Runtime timeout override:

@timeout(10)
def flexible_function():
    pass

# Override timeout at runtime
flexible_function(timeout=5)  # Will timeout after 5 seconds instead of 10

Disabled timeout:

@timeout()  # or @timeout(None)
def conditional_function():
    # No timeout applied
    pass

Exception Class

Custom exception raised when timeout occurs, extending Python's AssertionError.

class TimeoutError(AssertionError):
    """
    Thrown when a timeout occurs in the timeout decorator.
    
    Parameters:
    - value (str, default="Timed Out"): Error message
    """
    
    def __init__(self, value="Timed Out"):
        """Initialize TimeoutError with custom message."""
        
    def __str__(self):
        """Return string representation of the exception."""

Advanced Usage Patterns

Class Methods

The decorator works with class methods and instance methods:

class MyClass:
    @timeout(5)
    def instance_method(self):
        # Will timeout after 5 seconds
        pass
    
    @classmethod
    @timeout(3)
    def class_method(cls):
        # Will timeout after 3 seconds
        pass

Function Metadata Preservation

The decorator preserves original function metadata:

@timeout(5)
def documented_function():
    """This function has documentation."""
    pass

# Original function name and documentation are preserved
print(documented_function.__name__)  # "documented_function"
print(documented_function.__doc__)   # "This function has documentation."

Error Handling Strategy

from timeout_decorator import timeout, TimeoutError

@timeout(2)
def risky_operation():
    # Some operation that might take too long
    import requests
    return requests.get("https://httpbin.org/delay/5")

try:
    result = risky_operation()
    print("Operation completed successfully")
except TimeoutError:
    print("Operation timed out - implementing fallback")
    # Implement fallback logic
except Exception as e:
    print(f"Operation failed with error: {e}")
    # Handle other exceptions

Implementation Notes

Signal-based Strategy (default)

  • Uses signal.SIGALRM for timeout implementation
  • Works only in the main thread
  • Provides precise timeout control
  • Recommended for single-threaded applications

Multiprocessing Strategy

  • Creates a separate process to execute the function
  • Works in any thread or execution context
  • Timeout granularity limited to 0.01 seconds (10ms)
  • Required for web applications and multi-threaded contexts
  • Functions must return serializable objects (pickle-compatible)

Considerations

  • Signal limitations: Signal-based timeouts only work in the main thread
  • Serialization: When using use_signals=False, function arguments and return values must be pickle-serializable
  • Resource cleanup: Timed-out processes are automatically terminated
  • Precision: Multiprocessing strategy polls every 0.01 seconds for completion