SoFunction
Updated on 2025-04-20

Four ways to handle function call timeout

Preface

In actual development, we may encounter some scenarios where the execution time of the function needs to be limited. For example, when a function is executed for too long, it may cause program lag, resource usage too high, and even affect the stability of the entire system. Therefore, in some cases, we want to limit the maximum time of function calls to ensure that the program can complete the task within a reasonable time frame, or take other measures in case of timeout.

To achieve this, there are several ways to control the execution time of the function. For example, multithreading or asynchronous programming techniques can be used to monitor the execution of functions within a specified time range. If the function fails to complete execution within a specified time, the function can be interrupted and a timeout prompt or alternate logic can be executed. This method can not only improve the robustness of the program, but also effectively avoid system performance problems caused by the long execution time of a single function.

Limiting the maximum time of function calls is a very practical technical method that can help developers better control the behavior of programs, improve user experience, and ensure the stability and reliability of the system.

func-timeout

func-timeout is a Python library that allows setting timeouts for functions, preventing code from running for a long time or blocking infinitely. It is suitable for scenarios where execution time needs to be enforced, such as network requests, compute-intensive tasks, or code that may have a dead loop.

1. Install func-timeout

You can use pip to install:

pip install func-timeout

2. Basic usage

The most common way is func_timeout, which allows a function to be run within a specified time and an exception is thrown when a timeout is timed.

from func_timeout import func_timeout, FunctionTimedOut
import time
 
def long_running_task():
    (5)  # Simulate long-running tasks    return "Task completed"
 
try:
    result = func_timeout(3, long_running_task)  # Set 3 seconds timeout    print(result)
except FunctionTimedOut:
    print("Function execution timed out!")

explain:

  • func_timeout(3, long_running_task): Try running long_running_task in 3 seconds

  • FunctionTimedOut Exception indicates that the function timeout has not been completed

You can also use the decorator method to set the timeout for the function:

from func_timeout import func_set_timeout
import time
 
@func_set_timeout(2)  # Limit the running time of this function to 2 secondsdef long_task():
    (5)  # The task actually takes 5 seconds    return "Finished"
 
try:
    print(long_task())
except FunctionTimedOut:
    print("Function execution timed out!")

This method is suitable for functions that require multiple calls, avoiding manually setting timeouts for each call.

func-timeout is essentially dependent on multi-threading or multi-processing to implement timeout control, and may not be applicable to the main thread (such as Jupyter Notebook). It also cannot be used for while True dead loops within main thread, because Python's GIL may affect signal processing.

Custom processes

In addition to using the above library, you can also use one process to time and detect timeouts yourself, and another process to call Python functions. The following is the specific implementation code:

import time
from itertools import count
from multiprocessing import Process
 
def inc_forever():
    print('Starting function inc_forever()...')
    while True:
        (1)
        print(next(counter))
 
def return_zero():
    print('Starting function return_zero()...')
    return 0
 
if __name__ == '__main__':
    # counter is an infinite iterator    counter = count(0)
 
    p1 = Process(target=inc_forever, name='Process_inc_forever')
    p2 = Process(target=return_zero, name='Process_return_zero')
    ()
    ()
    (timeout=5)
    (timeout=5)
    ()
    ()
 
if  is None:
    print(f'Oops, {p1} timeouts!')
 
if  == 0:
    print(f'{p2} is luck and finishes in 5 seconds!')

The operation results are as follows:

Starting function inc_forever()...
Starting function return_zero()...
0
1
2
3
4
Oops, <Process(Process_inc_forever, started)> timeouts!
<Process(Process_return_zero, stopped)> is luck and finishes in 5 seconds!

From the exit code, it can be seen thatinc_forever()The function timed out (the exit code isNone),andreturn_zero()The function completed successfully in 5 seconds.

Subprocess parameter setting timeout

Starting with Python 3.5,subprocessThe module provides a convenient and recommendedrun()API, it has built-in timeout support. Here is the sample code:

import subprocess
 
r = (['echo', 'hello timeout'], timeout=5)
print(
    f'''type(r)={type(r)},
    ={},
    ={},
    ={},
    ={}'''
)
 
try:
    r = (['ping', ''], timeout=5)
except  as e:
    print(e)

The operation results are as follows:

hello timeout
type(r)=<class ''>,
    =['echo', 'hello timeout'],
    =0,
    =None,
    =None
PING  (216.58.194.164) 56(84) bytes of data.
64 bytes from ...: icmp_seq=1 ttl=54 time=10.4 ms
64 bytes from ...: icmp_seq=2 ttl=54 time=5.90 ms
64 bytes from ...: icmp_seq=3 ttl=54 time=6.19 ms
64 bytes from ...: icmp_seq=4 ttl=54 time=9.04 ms
64 bytes from ...: icmp_seq=5 ttl=54 time=16.7 ms
Command '['ping', '']' timed out after 5 seconds

When timeout, aTimeoutExpiredException.

Signals

For UNIX systems, you can also usesignalModule, throws an exception by sending a signal to the processor after 5 seconds. However, this method is relatively low-level and not intuitive enough.

import signal
def handler(signum, frame):
    raise TimeoutError("Function timeout")
def my_function():
    pass
(, handler)
(5)
try:
    my_function()
except TimeoutError:
    print("Function timeout")
finally:
    (0)

Summarize

In development, limiting the execution time of function is an important means to improve program stability and user experience. This article introduces several implementation methods:

  • func-timeout library:passfunc_timeoutOr decoratorfunc_set_timeout, can set the timeout time for the function, and an exception will be thrown when the timeout is. Suitable for network request or compute-intensive tasks.

  • Custom processes:UsemultiprocessingModule creation child process execution function, throughjoin(timeout)Control timeout and terminate the process after the timeout.

  • subprocess module: Starting from Python 3.5,()Supports timeout parameters, timeout will be thrownTimeoutExpiredException, suitable for external command calls.

  • Signaling mechanism: In UNIX systems, usesignalThe module sets a timeout signal, and an exception is triggered after the timeout, but the implementation is lower-level.

These methods have their own advantages and disadvantages, and developers can choose appropriate solutions based on actual needs.

The above is the detailed content of four methods for Python to handle function call timeouts. For more information about Python function call timeouts, please follow my other related articles!