问题的提出
假设你需要调用一个潜在的长函数,但你只能等待一个固定的时间段来终止该函数。
如果该函数在该时间间隔内终止,你将获得该函数的返回值。
如果函数没有在时间间隔内结束,你要取一个默认的(回退)值。
例子。
给出以下函数long_function() ,在一个无限的while循环中永远运行。
def long_function(n):
while True:
pass
在你的主代码中,你想运行该函数并等待一定的秒数,如变量max_wait 所示--但不能更长。
如果该函数在给定的时间限制内没有返回任何东西,你想默认返回一个指定的值(default_value )。
下面是你的run_function(func, max_wait, default_value) 应该如何工作。
def run_function(f, max_wait, default_value):
pass
x = run_function(long_function, 5, 'world')
print(x)
# world
函数run_function() 试图执行long_function() ,并等待5 秒。
由于long_function() 在指定的时限内没有返回任何值,run_function() 终止函数的执行,并返回在函数调用中为参数default_value 指定的默认值'world' 。
如何在Python中实现函数run_function() ?
解决方法
一个独立于平台且可移植的方法是限制函数调用的执行时间,使用模块的func_timeout.func_timeout() 函数。 [func_timeout](https://pypi.org/project/func-timeout/)模块。
这里是该函数的文档--但你不需要研究得太透彻,紧接着我将给你看一个简单的(最小的)例子。
func_timeout(timeout, func, args=(), kwargs=None)
函数func_timeout ,运行给定的函数,最长时间为timeout ,如果超过timeout ,就会引发FunctionTimedOut 的错误。
如果func 在指定的时间内返回一个值,func_timeout 将该返回值传递给调用者。
这些是文档中的参数。
timeout:终止前运行func的最大秒数func:要调用的函数args:任何有序的参数要传递给funckwargs:要传递的关键字参数func
让我们一步一步地解决这个问题吧!
安装和导入 func_timeout
在使用func_timeout 模块之前,你需要通过在终端、命令行或Powershell中运行pip install func_timeout 来安装它。
$ pip install func_timeout
下面是在我的Win Powershell中的样子。

要了解更多关于安装库的信息,请看这个指南。
安装后,你可以导入func_timeout 模块,并在你的Python代码中使用同名的func_timeout() 函数来限制特定函数的执行时间。
指导性解决方案实例
例子。让我们看一下下面的代码片段,它展示了如何解决指定的问题--我将在代码之后进行解释。
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
run_function() 的实现调用func_timeout.func_timeout(max_wait, long_function) ,在没有参数的情况下调用long_function() ,并等待max_wait 秒。
如果long_funcion() 在指定的时间间隔内没有终止,在long_function 的返回值转发给run_function() 的调用者之前,会引发一个错误并被 except 分支捕获。
默认值被返回--在我们的例子中是'world' 。
由于函数long_function() 花了很长时间,它不能返回字符串'universe' ,所以我们的代码使用默认输出'world' 。
函数通过
如果函数的运行时间不长,默认值就会被忽略。
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
因此,函数执行的输出是'universe' ,这是本例中没有花费太长时间的long_function() ,因为我们注释了无限的while循环。
函数参数
但是如果你想指定函数参数呢?
你可以通过使用func_timeout.func_timeout() 函数的args 参数来实现,该函数接收一个数值序列(例如,列表),并将这些数值传递给要执行的函数的参数。
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)
当然,你也可以通过指定一个长度大于1的列表作为func_timeout() 的参数来传递多个参数,像这样:args = [my_arg_1, my_arg_2, ..., my_arg_n] 将调用函数long_function(my_arg_1, my_arg_2, ..., my_arg_n) 。