max time wait for a function

Bryan bryanjugglercryptographer at yahoo.com
Tue May 18 09:22:23 EDT 2010


pacopyc  wrote:
> I'd like to call a function and waiting
> its return value for a time max (30 sec).
> The function could not respond and then I must avoid to wait for
> infinite time. OS is Windows XP.

You can do that using the multiprocessing module, which is in the
standard library of Python 2.6 or better. It has certain limitations,
but works on XP.

The functions have to be defined at module scope, and the arguments
and return value must be pickleable. The way multiprocessing works on
Windows, it launches a new process which runs the Python interpreter
on the module again, and pickles the arguments to pipe them to the new
process.

Below is a simple working demo/test. The demo uses a timeout of 1
second, rather than the specified 30, to avoid excessive boringness.
In practice, timeout_function() would be recklessly inefficient for
controlling quick operations; it creates a new pool of processes for
each function call that it might need to time-out. That's fixable, but
the question here is about a 30-second-plus processing problem, and in
that kind of case the overhead of creating one or a few new processes
is lost in the noise.

-Bryan Olson

#--------------------

from multiprocessing import Pool, TimeoutError

def timeout_function(timeout, f, args=(), kwargs={}):
    """ Return f(*args, **kwargs), or if that takes
        to long raise multiprocessing.TimeoutError.
    """
    pool = Pool(1)
    return pool.apply_async(f, args, kwargs).get(timeout)


#--------------
# simple demo-test:

from random import random as rand
from time import sleep

def sillyfunc(sleeptime):
    # Time-absorbing function for testing
    sleep(sleeptime)
    return 'Done.'

if __name__ == '__main__':
    timeout = 1.0
    print "Timeout is %f seconds" % timeout
    trials = 100
    ntimeouts = 0
    for _ in range(trials):

        # time-out probability a bit over 0.5
        sleeptime = rand() * timeout * 2

        try:
            result = timeout_function(
                        timeout,
                        sillyfunc,
                        (sleeptime,))
            assert result == 'Done.'
            print 'Ran without timing out'

        except TimeoutError:
            ntimeouts += 1
            print 'Timed out'
            if sleeptime < timeout:
                print '...Sucks! Slept %f' % sleeptime

    print 'Timed out %d out of %d' % (ntimeouts, trials)




More information about the Python-list mailing list