CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-futures

Backport of the concurrent.futures package from Python 3 for Python 2

Pending
Overview
Eval results
Files

futures.mddocs/

Future Objects

Future objects represent the result of an asynchronous computation. They provide methods to check the status of the computation, retrieve results, handle exceptions, and attach callbacks that execute when the computation completes.

Capabilities

Future Class

The Future class encapsulates the lifecycle and result of an asynchronous operation.

class Future:
    def __init__(self):
        """
        Initialize a Future object.
        
        Note: Should not be called directly by client code. 
        Futures are created by Executor.submit() calls.
        """
    
    def cancel(self):
        """
        Attempt to cancel the future.
        
        Returns:
        bool: True if successfully cancelled, False if already running or completed
        
        Note: Cannot cancel futures that are already running or finished
        """
    
    def cancelled(self):
        """
        Check if the future was cancelled.
        
        Returns:
        bool: True if the future was cancelled before completion
        """
    
    def running(self):
        """
        Check if the future is currently executing.
        
        Returns:
        bool: True if the future is currently being executed
        """
    
    def done(self):
        """
        Check if the future has completed.
        
        Returns:
        bool: True if future completed (finished, cancelled, or failed)
        """
    
    def result(self, timeout=None):
        """
        Get the result of the future.
        
        Parameters:
        - timeout (float, optional): Maximum time to wait in seconds
        
        Returns:
        Any: The result returned by the callable
        
        Raises:
        CancelledError: If the future was cancelled
        TimeoutError: If timeout exceeded before completion
        Exception: Any exception raised by the callable
        """
    
    def exception(self, timeout=None):
        """
        Get the exception raised by the future's callable.
        
        Parameters:
        - timeout (float, optional): Maximum time to wait in seconds
        
        Returns:
        Exception or None: Exception raised by callable, or None if successful
        
        Raises:
        CancelledError: If the future was cancelled
        TimeoutError: If timeout exceeded before completion
        """
    
    def exception_info(self, timeout=None):
        """
        Get exception and traceback information.
        
        Parameters:
        - timeout (float, optional): Maximum time to wait in seconds
        
        Returns:
        tuple: (exception, traceback) or (None, None) if successful
        
        Raises:
        CancelledError: If the future was cancelled
        TimeoutError: If timeout exceeded before completion
        """
    
    def add_done_callback(self, fn):
        """
        Attach a callback to be called when the future completes.
        
        Parameters:
        - fn (callable): Function to call with the future as argument
        
        Note: Callback is called immediately if future is already complete.
        Multiple callbacks are called in the order they were added.
        """

Usage Examples

Basic Future Usage:

from concurrent.futures import ThreadPoolExecutor

def slow_function(n):
    import time
    time.sleep(1)
    if n < 0:
        raise ValueError("Negative number")
    return n * n

with ThreadPoolExecutor() as executor:
    # Submit task and get future
    future = executor.submit(slow_function, 5)
    
    # Check status
    print(f"Cancelled: {future.cancelled()}")  # False
    print(f"Running: {future.running()}")      # True or False
    print(f"Done: {future.done()}")            # False initially
    
    # Get result (blocks until complete)
    result = future.result()
    print(f"Result: {result}")  # 25
    
    # Check final status
    print(f"Done: {future.done()}")  # True

Handling Exceptions:

with ThreadPoolExecutor() as executor:
    # Submit task that will raise exception
    future = executor.submit(slow_function, -1)
    
    try:
        result = future.result()
    except ValueError as e:
        print(f"Task failed: {e}")
    
    # Alternative: check exception directly
    exception = future.exception()
    if exception:
        print(f"Exception occurred: {exception}")

Using Timeouts:

with ThreadPoolExecutor() as executor:
    future = executor.submit(slow_function, 5)
    
    try:
        # Wait maximum 0.5 seconds
        result = future.result(timeout=0.5)
        print(f"Quick result: {result}")
    except TimeoutError:
        print("Task didn't complete in time")
        # Future continues running in background
        
        # Wait for actual completion
        result = future.result()  # No timeout
        print(f"Final result: {result}")

Cancelling Futures:

import time

with ThreadPoolExecutor() as executor:
    future = executor.submit(slow_function, 10)
    
    # Try to cancel immediately
    if future.cancel():
        print("Successfully cancelled")
    else:
        print("Could not cancel (already running)")
    
    # Check if cancelled
    if future.cancelled():
        try:
            result = future.result()
        except CancelledError:
            print("Future was cancelled")

Done Callbacks:

def task_completed(future):
    try:
        result = future.result()
        print(f"Task completed with result: {result}")
    except Exception as e:
        print(f"Task failed with exception: {e}")

with ThreadPoolExecutor() as executor:
    future = executor.submit(slow_function, 7)
    
    # Add callback (can add multiple)
    future.add_done_callback(task_completed)
    
    # Callback will be called when future completes
    # Main thread can continue other work
    result = future.result()  # Also wait for completion

Advanced Callback Usage:

def log_completion(name):
    def callback(future):
        status = "succeeded" if not future.exception() else "failed"
        print(f"Task '{name}' {status}")
    return callback

def process_result(future):
    if not future.exception():
        result = future.result()
        # Do something with result
        print(f"Processing result: {result}")

with ThreadPoolExecutor() as executor:
    future = executor.submit(slow_function, 3)
    
    # Add multiple callbacks
    future.add_done_callback(log_completion("calculation"))
    future.add_done_callback(process_result)
    
    # Both callbacks will be called when future completes
    future.result()

Future States and Lifecycle

A future progresses through these states:

  1. PENDING: Future created but not yet running
  2. RUNNING: Callable is currently executing
  3. CANCELLED: Future was cancelled before completion
  4. FINISHED: Callable completed (successfully or with exception)
# Example showing state transitions
with ThreadPoolExecutor(max_workers=1) as executor:
    def check_states(future, name):
        print(f"{name} - Cancelled: {future.cancelled()}, "
              f"Running: {future.running()}, Done: {future.done()}")
    
    future = executor.submit(slow_function, 2)
    check_states(future, "After submit")      # May show running=True
    
    result = future.result()
    check_states(future, "After completion")  # done=True

Error Handling Patterns

Comprehensive Error Handling:

from concurrent.futures import CancelledError, TimeoutError

def handle_future_result(future, timeout=None):
    try:
        result = future.result(timeout=timeout)
        return {"success": True, "result": result}
    except CancelledError:
        return {"success": False, "error": "cancelled"}
    except TimeoutError:
        return {"success": False, "error": "timeout"}
    except Exception as e:
        return {"success": False, "error": str(e)}

# Usage
with ThreadPoolExecutor() as executor:
    future = executor.submit(slow_function, 5)
    outcome = handle_future_result(future, timeout=2.0)
    
    if outcome["success"]:
        print(f"Result: {outcome['result']}")
    else:
        print(f"Failed: {outcome['error']}")

Internal Methods

These methods are primarily for use by Executor implementations:

def set_running_or_notify_cancel(self):
    """
    Mark future as running or notify cancellation.
    
    Returns:
    bool: False if cancelled, True if set to running
    
    Note: For internal use by executors
    """

def set_result(self, result):
    """
    Set the future's result.
    
    Parameters:
    - result: The result value
    
    Note: For internal use by executors
    """

def set_exception(self, exception):
    """
    Set the future's exception.
    
    Parameters:
    - exception: The exception that occurred
    
    Note: For internal use by executors
    """

def set_exception_info(self, exception, traceback):
    """
    Set the future's exception with traceback.
    
    Parameters:
    - exception: The exception that occurred  
    - traceback: The traceback information
    
    Note: For internal use by executors
    """

Install with Tessl CLI

npx tessl i tessl/pypi-futures

docs

executors.md

futures.md

index.md

utilities.md

tile.json