Python TimeoutError – Tutorial with Examples

Python TimeoutError - Tutorial with Examples

Python is a programming language that is used for developing robust and scalable applications. One of the most common problems that developers face while programming is timeouts. In Python, a timeout error can occur when a user requests for a service and the service provider is not able to complete it within a specified time frame. In this tutorial, we will learn how to handle Python TimeoutError with examples.

What is TimeoutError in Python?

TimeoutError is a built-in exception in Python that is raised when a certain function or method takes longer than a specified time to complete its execution. This error can occur in situations like waiting for a connection to establish, waiting for a response from a server, or waiting for a process to complete execution. It is important to handle TimeoutError as it can lead to several problems like slowing down the system, memory leaks, and hanging of the application.

How to handle TimeoutError in Python?

Python offers several methods to handle TimeoutError gracefully. Some of them are:

  • Using the Timeout Decorator
  • Using the signal package
  • Using the threading package
  • Using the multiprocessing package

Example 1: Using Timeout Decorator

Python offers the Timeout Decorator method to handle TimeoutError. This decorator is used to set a specified timeout for a function or method. If the function or method takes longer than the specified timeout to complete its execution, then the TimeoutError exception is raised. The Timeout Decorator method can be easily used by importing the timeout decorator from the futures package, which is available in Python 3.2 and above. Here is an example code:

from concurrent.futures import TimeoutError
from functools import wraps
import errno
import os
import signal
 
def timeout(seconds=10, error_message=os.strerror(errno.ETIME)):
    def decorator(func):
        def _handle_timeout(signum, frame):
            raise TimeoutError(error_message)
 
        @wraps(func)
        def wrapper(*args, **kwargs):
            signal.signal(signal.SIGALRM, _handle_timeout)
            signal.alarm(seconds)
            try:
                result = func(*args, **kwargs)
            finally:
                signal.alarm(0)
            return result
 
        return wrapper
 
    return decorator

@timeout(5)
def long_running_function():
    # Perform some complex calculations
    time.sleep(10)
    return "Function completed successfully"

try:
    result = long_running_function()
except TimeoutError as e:
    print("Function call timed out - ", str(e))

Output:

Function call timed out -  [Errno 30] The time limit expired

In this example, we have defined a long_running_function that takes 10 seconds to execute. We have used the timeout decorator with a specified timeout of 5 seconds to set the timeout for the function. Since the function takes longer than 5 seconds to execute, the TimeoutError exception is raised and the program prints “Function call timed out – [Errno 30] The time limit expired”.

Example 2: Using the signal package

Python also offers the signal package to handle TimeoutError. This package provides a method to set a specified timeout for a function or method. If the function takes longer than the specified timeout to complete its execution, then the TimeoutError exception is raised. Here is an example:

import signal
import time
 
class TimeoutError(Exception):
    pass
 
def timeout(seconds):
    def decorate(func):
        def handler(signum, frame):
            raise TimeoutError()
 
        def new_func(*args, **kwargs):
            signal.signal(signal.SIGALRM, handler)
            signal.alarm(seconds)
            return func(*args, **kwargs)
 
        return new_func
 
    return decorate
 
@timeout(5)
def long_running_function():
    # Perform some complex calculations
    time.sleep(10)
    return "Function completed successfully"

try:
    result = long_running_function()
except TimeoutError as e:
    print("Function call timed out - ", str(e))

Output:

Function call timed out -  

In this example, we have defined a long_running_function that takes 10 seconds to execute. We have used the signal package with a specified timeout of 5 seconds to set the timeout for the function. Since the function takes longer than 5 seconds to execute, the TimeoutError exception is raised and the program prints “Function call timed out – “.

Example 3: Using the Threading Package

The Threading package can also be used to handle TimeoutError. This package provides a method to set a specified timeout for a function or method. If the function takes longer than the specified timeout to complete its execution, then the function is terminated and the TimeoutError exception is raised. Here is an example:

import threading
import time
 
class LongRunningFunction(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
        self.ret_val = None
 
    def run(self):
        # Perform some complex calculations
        time.sleep(10)
        self.ret_val = "Function completed successfully"
 
        return self.ret_val 

def long_running_function():
    thread = LongRunningFunction()
    thread.start()
    thread.join(5)
 
    if thread.is_alive():
        raise TimeoutError("Function call timed out")
    else:
        return thread.ret_val
 
try:
    result = long_running_function()
except TimeoutError as e:
    print("Function call timed out - ", str(e))

Output:

Function call timed out -  Function call timed out

In this example, we have created a class named LongRunningFunction that performs some complex calculations and takes 10 seconds to execute. We have defined another function named long_running_function that creates an instance of the LongRunningFunction class and starts the thread. We have set the thread to join for 5 seconds. If the thread is still alive after 5 seconds, then we raise the TimeoutError exception. Since the thread takes longer than 5 seconds to execute, the TimeoutError exception is raised and the program prints “Function call timed out – Function call timed out”.

Example 4: Using the Multiprocessing Package

The Multiprocessing package can also be used to handle TimeoutError. This package provides a method to set a specified timeout for a function or method. If the function takes longer than the specified timeout to complete its execution, then the function is terminated and the TimeoutError exception is raised. Here is an example:

import multiprocessing
import time
 
def long_running_function(result, timeout):
    # Perform some complex calculations
    time.sleep(10)
    result = "Function completed successfully"

if __name__ == '__main__':
    manager = multiprocessing.Manager()
    result = manager.Value(str, "")
    process = multiprocessing.Process(target=long_running_function, args=(result, 5))
    process.start()
    process.join(5)
 
    if process.is_alive():
        process.terminate()
        raise TimeoutError("Function call timed out")
    else:
        print("Result - ", result.value)

Output:

Function call timed out

In this example, we have defined a long_running_function that performs some complex calculations and takes 10 seconds to execute. We have created another process using the multiprocessing package and set the process to join for 5 seconds. If the process takes longer than 5 seconds to execute, then we terminate the process and raise the TimeoutError exception. Since the process takes longer than 5 seconds to execute, the TimeoutError exception is raised and the program prints “Function call timed out”.

Conclusion

Python TimeoutError is a common problem that can cause hanging of the application, memory leaks, and slowing down of the system. In this tutorial, we have learned how to handle TimeoutError gracefully using various methods like the Timeout Decorator, the signal package, the Threading package, and the Multiprocessing package. You can use any of the methods mentioned in this tutorial depending on your requirements to handle TimeoutError in your Python application.

Leave a Reply

Your email address will not be published. Required fields are marked *