我有一个函数,我们称之为my_function(*args, **kwargs)
,根据传递给它的参数,它需要30秒到很多小时(天)。我有一个不同参数的列表,我想知道函数在给定参数的情况下需要多长时间。
我仍然很擅长使用timeit
,但我已经学到了足够的知识来完成这一部分;但是,这对我的目的来说不是很有效。尽管所有这些参数都可以在“有限”时间内解决,但任何需要超过4小时才能完成的参数都会被认为是难以处理的。由于一些(可能是大多数)参数将导致运行时间超过20小时,我正在寻找一种方法来在4小时后终止测试,这样我就不必浪费时间来搞清楚这是棘手的。
我查看了Timeout on a Python function call和Stop code after time period,这可能是一个重复的问题,但我无法将这些答案与timeit
整合在一起记录的时间少于4小时,长时间运行会返回大于4小时的有效时间。
这样做最好的方法是什么?
编辑:我遇到的一个问题是,我看到的答案在func(*args,**kwargs)
timeit
,而timeit.Timer('my_function(*args, **kwargs)', setup=setup).timeit(1)
函数看起来像这样:
def foo(x):
for i in xrange(1, x + 1):
sleep(1)
print i
return x
我不知道如何处理这张表格。
编辑:我在下面使用线程提供的原始答案实际上并不终止线程。通过以下功能运行它可以很容易地显示出来。
multiprocessing.Pool
使用涉及terminate()
的代码,实际上有{{1}},允许这样做。
答案 0 :(得分:1)
基于Timeout function using threading in python does not work中的答案。如果你在foo(x)
上试一试,它确实会停止计数,这与我以前的答案不同。
import multiprocessing as mp
import timeit
def timeout(func, args=(), kwargs=None, TIMEOUT=10, default=None, err=.05):
if hasattr(args, "__iter__") and not isinstance(args, basestring):
args = args
else:
args = [args]
kwargs = {} if kwargs is None else kwargs
pool = mp.Pool(processes = 1)
try:
result = pool.apply_async(func, args=args, kwds=kwargs)
val = result.get(timeout = TIMEOUT * (1 + err))
except mp.TimeoutError:
pool.terminate()
return default
else:
pool.close()
pool.join()
return val
def Timeit(command, setup=''):
return timeit.Timer(command, setup=setup).timeit(1)
def timeit_timeout(command, setup='', TIMEOUT=10, default=None, err=.05):
return timeout(Timeit, args=command, kwargs={'setup':setup},
TIMEOUT=TIMEOUT, default=default, err=err)
答案 1 :(得分:0)
经过一些小小的讨论后,我得到了基于Timeout function using threading的初步答案。我仍然希望听到任何有更好想法的人,因为我还是新手。
def timeout(func, args=None, kwargs=None, TIMEOUT=10, default=None, err=.05):
if args is None:
args = []
elif hasattr(args, "__iter__") and not isinstance(args, basestring):
args = args
else:
args = [args]
kwargs = {} if kwargs is None else kwargs
import threading
class InterruptableThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.result = None
def run(self):
try:
self.result = func(*args, **kwargs)
except:
self.result = default
it = InterruptableThread()
it.start()
it.join(TIMEOUT* (1 + err))
if it.isAlive():
return default
else:
return it.result
def timeit_timeout(command, setup='', TIMEOUT=10, default=None, err=.05):
import timeit
f = lambda: timeit.Timer(command, setup=setup).timeit(1)
return timeout(f,TIMEOUT=TIMEOUT, default=default, err=err)
if __name__ == '__main__':
from time import sleep
setup = 'gc.enable()\nfrom time import sleep'
for n in range(1,15):
command = 'sleep({})'.format(n)
print timeit_timeout(command, setup=setup, default=float('Inf'))