Hi,
sometimes my one of function work too long.
How i can break my function, if this function work longer than 3 seconds?

thanks

You should launch it in thread and kill it if result is not ready after 3 seconds. It more likely means that you have bad design for the function. What you want to do?

Another way: If your function has a loop like this

def myfunc(*args):
    something = initial_value
    while True:
        # your work here
    return something

Then you can check if the loop has run too long with a call to time.time() like this:

import time
def myfunc(*args):
    start = time.time()
    something = initial_value
    while True:
        # your work here
        if time.time() - start > 3.0:
            raise Exception("myfunc ran more than 3 seconds")
    return something

The downside of this is that the time.time() system call isn't free, so your loop will run slower.

P.S. I agree with Tony: You will probably get better results by figuring out why the function "sometimes" runs too long. If "approximate" values are good enough, perhaps you can just count iterations, or notice how close together the last two approximations were, and break the loop when the answer is good enough.

Gris has good alternative and I have used the approach in some of my programs, gets little taugh if the function is recursive though.

More efficient way is to record end time (which could be necessary as this kind of situation usually arise from compute intensive tight loop situation):

import time
def myfunc(*args):
    end = time.time() + 3.0
    something = initial_value
    while True:
        # your work here
        if time.time() >= end:
            raise Exception("myfunc ran more than 3 seconds")
    return something

Asumed your algorithm is OK, have you tried to use your program with PyPy or Python2.6 with Psyco.

Even you could make the tight loop code to module and use ShedSkin as I used for my Mandelbrot program (ah memories from 80's BASIC programming!)

Or if you are producing multiple solutions from your function, you could consider yielding them from generator one by one. For numeric problems there is also the numpy module.

Edited 5 Years Ago by pyTony: yield, numpy

Tony's idea to move the subtraction outside the loop is good.

If using recursion, you merely carry the initial time() value along as a parameter:

import time
def my_recursive_func(stoptime = time.time() + 3.0, *args):
    # blah blah blah
    if time.time() > stoptime:
        raise Exception("too long")
    if not stopping_condition(*args):
         something = my_recursive_func(stoptime, *args)
    # blah blah blah

Now, on the first call, you get defaulted stoptime, and in the recursions, you simply pass it along so the default isn't triggered.

Edited 5 Years Ago by griswolf: n/a

"Runs too long" usually means an infinite loop in today's fast CPU world, so if the program is interrupted after a certain period of time, the results may not be correct.

"Runs too long" usually means an infinite loop in today's fast CPU world, so if the program is interrupted after a certain period of time, the results may not be correct.

I've written programs that ran for weeks in order to do something useful (the results were cached for later fast access).

I've written programs that approximated a value, which were able to stop after some "close enough" or "long enough" condition was met: The result isn't perfect, but it may be more useful than nothing. Mandelbrot visualization, for one example.

OP says that "sometimes" the program runs too long so the problem isn't a "simple" infinite loop (of course it might be that some data sets cause logic branches that make a loop that never stops)

Tony's idea to move the subtraction outside the loop is good.

If using recursion, you merely carry the initial time() value along as a parameter:

import time
def my_recursive_func(stoptime = time.time() + 3.0, *args):
    # blah blah blah
    if time.time() > stoptime:
        raise Exception("too long")
    if not stopping_condition(*args):
         something = my_recursive_func(stoptime, *args)
    # blah blah blah

Now, on the first call, you get defaulted stoptime, and in the recursions, you simply pass it along so the default isn't triggered.

Of course then the finishing time must be three second from time of definition:

import time
def my_recursive_func(stoptime = time.time() + 3.0, *args):
    # blah blah blah
    if time.time() > stoptime:
        raise Exception("too long")
    if not stopping_condition(*args):
         something = my_recursive_func(stoptime, *args)

time.sleep(4.0)
my_recursive_func()
"""Traceback (most recent call last):
  File "C:/Python27/timeout.py", line 10, in <module>
    my_recursive_func()
  File "C:/Python27/timeout.py", line 5, in my_recursive_func
    raise Exception("too long")
Exception: too long
"""

Usually better to leave out default and leave filling it for caller or:

def my_recursive_func(stoptime = lambda: (time.time() + 3.0), *args):
This article has been dead for over six months. Start a new discussion instead.