max time wait for a function

P

pacopyc

Hi, I've a question for you. 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.
Can you help me?

Thank
 
A

Albert Hopkins

Hi, I've a question for you. 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.
Can you help me?

Thank

This is how I do it with a function decorator. I probably borrowed this
from someone and not attributed it. Anyway, it works on Linux, not sure
about Windows:

def function_timeout(seconds):
"""Function decorator to raise a timeout on a function call"""
import signal
class FunctionTimeOut(Exception):
pass

def decorate(f):
def timeout(signum, frame):
raise FunctionTimeOut()

def funct(*args, **kwargs):
old = signal.signal(signal.SIGALRM, timeout)
signal.alarm(seconds)

try:
result = f(*args, **kwargs)
finally:
signal.signal(signal.SIGALRM, old)
signal.alarm(0)
return result

return funct

return decorate
 
B

Bryan

pacopyc said:
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)
 
T

Terry Reedy

This is how I do it with a function decorator. I probably borrowed this
from someone and not attributed it. Anyway, it works on Linux, not sure
about Windows:

def function_timeout(seconds):
"""Function decorator to raise a timeout on a function call"""
import signal
class FunctionTimeOut(Exception):
pass

def decorate(f):
def timeout(signum, frame):
raise FunctionTimeOut()

def funct(*args, **kwargs):
old = signal.signal(signal.SIGALRM, timeout)
signal.alarm(seconds)

from help(signal):
alarm() -- cause SIGALRM after a specified time [Unix only]

I do not know of any replacement in the stdlib, but one could check the
code for multiprocessing to see how it does a timeout. Or check the
pywin32 library
http://pypi.python.org/pypi/pywin32/210
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top