Timeout Function in Python 3

Every Python application eventually encounters operations that take longer than expected. External APIs go down. Database queries hit performance bottlenecks. File processing jobs receive unexpectedly large inputs. Without proper controls, these scenarios drain system resources and degrade service quality for all users. Have you ever implemented a function that has to stop its execution after […]

by Veselin Pavlov

November 15, 2016

8 min read

timeout - Timeout Function in Python 3

Every Python application eventually encounters operations that take longer than expected. External APIs go down. Database queries hit performance bottlenecks. File processing jobs receive unexpectedly large inputs. Without proper controls, these scenarios drain system resources and degrade service quality for all users.

Have you ever implemented a function that has to stop its execution after certain period of time? It is not as easy as it sounds, is it?  Working at a custom software development company, I had to develop such timeout function in Python for a customer who had a requirement that one activity shouldn’t take more than 180 seconds to execute. This type of challenge is more common than you might think - whether you're enforcing SLA commitments, managing cloud costs, or preventing cascading failures in distributed systems.

There are two approaches to achieve this behavior. The first one is to use threads and the second one, to use processes. The second one is better, in my opinion, but in this article I will discuss both of them. Understanding both methods helps you make informed architectural decisions based on your specific business requirements and technical constraints.

What is timeout function in Python?

A timeout function in Python is a control mechanism that stops code execution after a predetermined time limit, preventing operations from running indefinitely. Think of it as an automatic circuit breaker for your applications.

When your Python code calls an external service, queries a database, or processes data, a timeout function ensures that if the operation doesn't complete within the specified timeframe, say 5 seconds or 3 minutes, the system automatically terminates it and moves on. 

This differs from normal function execution where code runs until it finishes, regardless of how long that takes. For business applications, timeout functions provide predictable behavior: instead of waiting indefinitely for a failing payment gateway to respond, your checkout process fails fast, logs the issue, and presents the customer with a retry option. Python offers two primary implementation approaches: thread-based timeouts, which work well for most internal operations, and process-based timeouts, which provide stronger guarantees when dealing with external libraries or third-party code. The choice between these methods affects how reliably your application can terminate stuck operations, making it a relevant consideration for technical leaders planning resilient systems.

Read next: Top 10 Python Software Development Companies in Europe

timeout function in python, python business applications, python for custom software development, Python development company Dreamix

Implementing Python timeout function with thread

In order to implement the timeout function, we need one thread to execute the function and another to watch the time that it takes. When the time is over only the second thread knows it. If we could simply kill the function thread everything would work as expected but since they share the same execution context, we can’t. Threads can’t be killed so what we can do is to signal the other thread that it should stop.

The drawback of this approach, however, is that it can’t be used in all the cases. For example if we are using an external library inside that function, the execution might be stuck in a code that we don’t have access to. In this case we can’t guarantee that the function will stop exactly after the given period. But in most of the cases this approach is enough. In the first thread (the one that executes the function) we have to make regular checks if the time is over. We can use the Event object from the threading module in Python 3 to send a signal from one thread to another. Here is an example:

Example:

from threading import Thread, Event
import time


# Event object used to send signals from one thread to another
stop_event = Event()


def do_actions():
    """
    Function that should timeout after 5 seconds. It simply prints a number and waits 1 second.
    :return:
    """
    i = 0
    while True:
        i += 1
        print(i)
        time.sleep(1)

        # Here we make the check if the other thread sent a signal to stop execution.
        if stop_event.is_set():
            break


if __name__ == '__main__':
    # We create another Thread
    action_thread = Thread(target=do_actions)

    # Here we start the thread and we wait 5 seconds before the code continues to execute.
    action_thread.start()
    action_thread.join(timeout=5)

    # We send a signal that the other thread should stop.
    stop_event.set()

    print("Hey there! I timed out! You can do things after me!")

Result:
1
2
3
4
5
Hey there! I timed out! You can do things after me!

In this example the main thread waits 5 seconds before it sends a stop_event signal. This is implemented with the join method which purpose is to block the calling thread until the thread whose join() method is called is terminated or the period set in the timeout parameter is over.

After the blocking goes off, the main thread sends the stop signal and the other thread is supposed to see it and stop. If we have a loop with many fast actions, this approach is appropriate but if we call some functions from external modules we can’t guarantee that after the 5 seconds, the thread will be able to see that it should stop. Fortunately Python provides the multiprocessing module, which allows us to create processes which can be killed.

Implementing timeout function with Process

As I said earlier threads can’t be killed because they have shared memory and some resources like files, database connections might be left unreleased if we kill the threads forcefully.

This is not true for processes. Each process has it’s own memory space. This allows us to kill it without worrying that it might leave some open resource.

Below is the same example implemented with process:

Example:

from multiprocessing import Process
import time

def do_actions():
    """
    Function that should timeout after 5 seconds. It simply prints a number and waits 1 second.
    :return:
    """
    i = 0
    while True:
        i += 1
        print(i)
        time.sleep(1)

if __name__ == '__main__':
    # We create a Process
    action_process = Process(target=do_actions)

    # We start the process and we block for 5 seconds.
    action_process.start()
    action_process.join(timeout=5)

    # We terminate the process.
    action_process.terminate()
    print("Hey there! I timed out! You can do things after me!")

Result:
1
2
3
4
5
Hey there! I timed out! You can do things after me!

As you can see from the code we use the terminate function of the process to stop it. Keep in mind that the termination process might take some time so in both cases we can’t guarantee that it will take exactly 5 seconds to finish but at least with processes it will be closer.

Do you know another way to implement this behavior?

The timeout function in Python applications serve as a critical safeguard for your business operations. When your Python-based services process customer requests, API calls, or data operations, any single task that hangs indefinitely can cascade into broader system failures.

For organisations running Python applications at scale, timeout controls mean the difference between predictable performance and unexpected outages. If your e-commerce platform processes thousands of transactions per hour, a single stuck database query without a timeout can exhaust your connection pool, blocking all subsequent customer orders. The financial impact is immediate and measurable.

Python's flexibility makes it a popular choice for business applications, but this same flexibility requires deliberate timeout implementation. Your development teams need these controls to ensure your applications remain resilient under real-world conditions where third-party APIs fail, network connections drop, or unexpected data volumes arrive.

Applications without timeout mechanisms create three major business risks:

Resource exhaustion costs you money. In cloud environments where you pay for compute time, hung processes continue consuming CPU, memory, and database connections even though they produce no value. According to Statista, cloud infrastructure spending reached $561 billion in 2024, making resource efficiency a direct bottom-line concern.

Service degradation damages customer relationships. When Python workers get stuck waiting for responses that never arrive, your application's capacity shrinks. Customer-facing features slow down or stop responding entirely. User sessions timeout, shopping carts are abandoned, and support ticket volume increases.

Debugging becomes expensive. Without timeout controls, your teams spend hours tracking down why systems froze, analysing logs, and attempting to reproduce intermittent failures. This diverts engineering resources from feature development to firefighting, extending your time-to-market for new capabilities.

Your teams should implement a timeout function in Python applications whenever code execution depends on external factors beyond your direct control:

External API integrations. Any time your Python application calls third-party services—payment processors, shipping carriers, data providers, or partner APIs—you need timeout protection. These external dependencies can experience latency, outages, or rate limiting that your application must handle gracefully.

Database operations. Complex queries, large data exports, or operations on distributed databases can take unpredictable amounts of time. Timeout controls prevent a single problematic query from monopolising database connections your entire application depends on.

User-generated workloads. When your Python application processes file uploads, runs analytics on customer data, or executes custom business logic, timeout functions protect against edge cases where input data causes unexpectedly long processing times.

Microservices communication. In distributed architectures where Python services call each other, timeout controls prevent cascading failures where one slow service degrades your entire system.

Timeout controls translate directly into cost savings and operational stability:

Cloud cost reduction. Python processes that terminate after defined timeouts release compute resources back to your pool. In serverless environments like AWS Lambda or Google Cloud Functions, this means you stop paying for execution time the moment a timeout occurs rather than waiting for the maximum function duration. For organisations processing millions of requests monthly, even small efficiency gains compound into significant savings.

Capacity planning accuracy. When you know the maximum time any Python operation can consume, you can accurately calculate how many concurrent users your infrastructure supports. This prevents over-provisioning (wasted budget on unused capacity) and under-provisioning (customer-facing performance issues).

Database license optimization. Many enterprise databases charge based on concurrent connections. Timeout functions ensure that connections are released promptly, reducing the total connection pool size you need to license and maintain.

Engineering productivity. According to HBR, high-performing engineering teams spend almost half of their time on new features vs maintenance. Timeout controls reduce production incidents, freeing your Python developers to focus on business value rather than troubleshooting hung processes.

We’d love to hear about your Python software project and help you meet your business goals as soon as possible.

Categories

As an Engineering Manager and Partner at Dreamix, Veselin has extensive experience across all areas of software development, leading complex enterprise projects to successful delivery. His diverse project portfolio spans in transportation and logistics, ESG, media, telecommunications and more.