Problem Formulation
Say you need to call a potentially long function but you can only wait for a fixed time duration for the function to terminate.
If the function does terminate within the time interval, you take the function’s return value.
If the function does not terminate within the time interval, you want to take a default (fallback) value.
Example:
Given the following function long_function()
that runs forever in an infinite while loop:
def long_function(n): while True: pass
In your main code, you want to run the function and wait for a certain number of seconds as given by variable max_wait
—but not longer.
If the function doesn’t return anything within the given time constraint, you want to return a specified value by default (default_value
).
Here’s how your run_function(func, max_wait, default_value)
should work:
def run_function(f, max_wait, default_value): pass x = run_function(long_function, 5, 'world') print(x) # world
The function run_function()
attempts to execute the long_function()
and waits for 5
seconds.
As long_function()
doesn’t return any value within the specified time limit, run_function()
aborts the function execution and returns the default value 'world'
as specified in the function call for argument default_value
.
How to implement the function run_function()
in Python?
Solution
A platform-independent and portable way to limit the execution time of a function call, use the func_timeout.func_timeout()
function of the func_timeout
module.
Here’s the documentation of the function—but you don’t need to study it too thoroughly, I’ll show you a simple (minimal) example right afterward:
func_timeout(timeout, func, args=(), kwargs=None)
The function func_timeout
runs the given function for up to timeout
seconds and raises a FunctionTimedOut
error if the timeout
is exceeded.
If the func
returns a value within the specified time, func_timeout
passes that return value to the caller.
These are the arguments from the docs:
timeout
: Maximum number of seconds to runfunc
before terminatingfunc
: The function to callargs
: Any ordered arguments to pass tofunc
kwargs
: Keyword arguments to pass tofunc
Let’s get this problem solved step by step!
Install and Import func_timeout
Before using the func_timeout
module, you need to install it by running pip install func_timeout
in your terminal, command line, or Powershell:
$ pip install func_timeout
Here’s how that looks in my Win Powershell:
To learn more about installing libraries, have a look at this guide.
After installation, you can import the func_timeout
module and use the func_timeout()
function with the same name in your Python code to limit the execution time of a given function.
Guided Solution Example
Example: Let’s have a look at the following code snippet that showcases how to solve the specified problem—I’ll explain it subsequently after the code:
import func_timeout def long_function(): while True: pass return 'universe' def run_function(f, max_wait, default_value): try: return func_timeout.func_timeout(max_wait, long_function) except func_timeout.FunctionTimedOut: pass return default_value x = run_function(long_function, 5, 'world') print(x) # world
The run_function()
implementation calls func_timeout.func_timeout(max_wait, long_function)
to call long_function()
without arguments and wait for max_wait
seconds.
If the long_funcion()
doesn’t terminate within the specified time interval, an error is raised and caught by the except branch before the return value of long_function
can be forwarded to the caller of run_function()
.
The default value is returned—which is 'world'
in our example.
As the function long_function()
took forever, it couldn’t return the string 'universe'
, so our code uses the default output 'world'
.
Function Goes Through
If the function doesn’t take too long to run, the default value is ignored:
import func_timeout def long_function(): # while True: pass return 'universe' def run_function(f, max_wait, default_value): try: return func_timeout.func_timeout(max_wait, long_function) except func_timeout.FunctionTimedOut: pass return default_value x = run_function(long_function, 5, 'world') print(x) # universe
Thus, the output of the function execution is 'universe'
which is the return value of the long_function()
that didn’t take too long in this example as we commented out the infinite while loop.
Function Arguments
But what if you want to specify function arguments?
You can do so by using the args
argument of the func_timeout.func_timeout()
function that takes a sequence (e.g., list) of values and passes these values into the argument of the function to be executed.
import func_timeout def long_function(my_argument): print(my_argument) while True: pass return 'universe' def run_function(f, my_argument, max_wait, default_value): try: return func_timeout.func_timeout(max_wait, long_function, args=[my_argument]) except func_timeout.FunctionTimedOut: pass return default_value x = run_function(long_function, 'started execution', 5, 'world') print(x)
Of course, you can also pass multiple arguments by specifying a list of length larger than 1 as an argument to func_timeout()
like so: args = [my_arg_1, my_arg_2, ..., my_arg_n]
will call the function long_function(my_arg_1, my_arg_2, ..., my_arg_n)
.