Is there a better way to implement this:

Discussion in 'Python' started by Michael Yanowitz, Jan 22, 2007.

  1. Hello:

    I wrote the code below (much irrelevant code removed).
    This doesn't quite work. What I wanted it to do was
    a) Execute function ftimed, which takes a function and a timeout
    in seconds.
    b) This will also execute function abort() as a thread.
    This function just runs for the specified
    number of seconds and returns.
    However, before it returns, throws an exception.
    c) If test() is still running when abort() is
    finished, ftimed() should catch the exception and
    return.

    It is catching the exception, however it continues running the function.
    Why does it continue and not return?

    What am I missing, or is there a better way to
    implement this (having ftimed() return when the
    abort-timer time is exceeded?


    import time, thread, sys

    thread_finished = "MAX RUN TIME EXCEEDED!"

    def abort (seconds):
    start_time = time.time()
    while ((time.time() - start_time) < seconds):
    time.sleep(0.01)
    print "script run time exceeded max_run_time of", seconds, "seconds."
    raise thread_finished
    return


    def test():
    i = 0
    while (True):
    time.sleep(1)
    print "HELLO", i
    i+=1


    def ftimed (func, seconds):
    thread.start_new_thread (abort, (seconds,))

    try:
    func()
    except thread_finished:
    print "Timeout"
    return

    ftimed (test, 30)
    print "Script finished"

    It presently generates the following output:
    $ python ./testthread.py
    HELLO 0
    HELLO 1
    HELLO 2
    HELLO 3
    HELLO 4
    HELLO 5
    HELLO 6
    HELLO 7
    HELLO 8
    HELLO 9
    HELLO 10
    HELLO 11
    HELLO 12
    HELLO 13
    HELLO 14
    HELLO 15
    HELLO 16
    HELLO 17
    HELLO 18
    HELLO 19
    HELLO 20
    HELLO 21
    HELLO 22
    HELLO 23
    HELLO 24
    HELLO 25
    HELLO 26
    HELLO 27
    HELLO 28
    HELLO 29
    script run time exceeded max_run_time of 30 seconds.
    Unhandled exception in thread started by <function abort at 0x009CEF30>
    Traceback (most recent call last):
    File "./testthread.py", line 10, in abort
    raise thread_finished
    MAX RUN TIME EXCEEDED!
    HELLO 30
    HELLO 31
    HELLO 32
    .....



    Thanks in advance:
    Michael Yanowitz
    Michael Yanowitz, Jan 22, 2007
    #1
    1. Advertising

  2. Michael Yanowitz wrote:

    > Hello:
    >
    > I wrote the code below (much irrelevant code removed).
    > This doesn't quite work. What I wanted it to do was
    > a) Execute function ftimed, which takes a function and a timeout
    > in seconds.
    > b) This will also execute function abort() as a thread.
    > This function just runs for the specified
    > number of seconds and returns.
    > However, before it returns, throws an exception.
    > c) If test() is still running when abort() is
    > finished, ftimed() should catch the exception and
    > return.
    >
    > It is catching the exception, however it continues running the function.
    > Why does it continue and not return?


    The exception is raised in the thread that executes the abort() function.
    The exception does not get caught and terminates this thread. The other
    (main) thread is unaffected - exceptions are local to a thread and there is
    currently no (portable) way to raise an exception in another thread.

    > What am I missing, or is there a better way to
    > implement this (having ftimed() return when the
    > abort-timer time is exceeded?


    You may use the signal.alarm() function, if you are on a UNIXoid system and
    you have only a signle time-out at a time (e.g. not nested).

    > import time, thread, sys
    >
    > thread_finished = "MAX RUN TIME EXCEEDED!"
    >
    > def abort (seconds):
    > start_time = time.time()
    > while ((time.time() - start_time) < seconds):
    > time.sleep(0.01)


    any reason for not using time.sleep(seconds) here?

    > print "script run time exceeded max_run_time of", seconds, "seconds."
    > raise thread_finished
    > return
    >
    >
    > def test():
    > i = 0
    > while (True):
    > time.sleep(1)
    > print "HELLO", i
    > i+=1
    >
    >
    > def ftimed (func, seconds):
    > thread.start_new_thread (abort, (seconds,))
    >
    > try:
    > func()
    > except thread_finished:
    > print "Timeout"
    > return
    >
    > ftimed (test, 30)
    > print "Script finished"


    --
    Benjamin Niemann
    Email: pink at odahoda dot de
    WWW: http://pink.odahoda.de/
    Benjamin Niemann, Jan 22, 2007
    #2
    1. Advertising

  3. Michael Yanowitz

    Paul Boddie Guest

    Michael Yanowitz wrote:
    >
    > I guess I am looking for something portable (both
    > Windows and Linux) where I can abort a function after
    > a certain time limit expires.


    Doing a search for "timeout function Python" on Google reveals a number
    of approaches.

    Using signals:

    * http://nick.vargish.org/clues/python-tricks.html
    * http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/307871

    Using threads:

    * http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/473878

    Using processes:

    * http://lfw.org/python/delegate.html

    Paul
    Paul Boddie, Jan 22, 2007
    #3
  4. Michael Yanowitz

    Peter Otten Guest

    Paul Boddie wrote:

    > Michael Yanowitz wrote:
    >>
    >> I guess I am looking for something portable (both
    >> Windows and Linux) where I can abort a function after
    >> a certain time limit expires.

    >
    > Doing a search for "timeout function Python" on Google reveals a number
    > of approaches.


    > Using threads:
    >
    > * http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/473878


    That doesn't abort the calculation, however -- it just moves on with a
    default value instead of the actual result if that is not available after
    the specified timespan.

    The calculation may go on forever eating up resources.

    Peter
    Peter Otten, Jan 23, 2007
    #4
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Peter Bencsik
    Replies:
    2
    Views:
    826
  2. mike3
    Replies:
    19
    Views:
    572
    mike3
    Apr 29, 2008
  3. Paul Rubin
    Replies:
    5
    Views:
    416
    Hendrik van Rooyen
    Aug 6, 2009
  4. david.karr
    Replies:
    23
    Views:
    2,158
    Arne Vajhøj
    Jan 3, 2010
  5. Replies:
    2
    Views:
    52
    Mark H Harris
    May 13, 2014
Loading...

Share This Page