2

我有一个函数,我们称之为它my_function(*args, **kwargs),根据传递给它的参数,它需要 30 秒到很多小时(天)。我有一个不同参数的列表,我想知道给定参数的函数需要多长时间。

我对使用仍然很陌生timeit,但我已经学到了足够的知识来完成这部分;但是,这对我的目的来说不是很有效。任何需要超过 4 小时才能完成的论点都被认为是棘手的,尽管它们都能够在“有限”时间内解决。由于某些(可能是大多数)参数会导致运行时间超过 20 小时以上,我正在寻找一种在 4 小时后终止测试的方法,这样我就不必在弄清楚之后浪费时间了这是棘手的。

我查看了Timeout on a Python function callStop 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(), 的代码允许这样做。

4

2 回答 2

2

根据Timeout function using threading in python 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) 
于 2013-12-31T19:55:33.140 回答
0

经过一番摆弄后,我有了一个基于Timeout 函数使用 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'))
于 2013-12-03T21:47:45.557 回答