5

For example i have function do_something() and I want it to run for exactly 1 second (and not .923 seconds. It won't do. However 0.999 is acceptable.)

However it is very very important that the do_something must exactly run for 1 second. I was thinking of using UNIX time stamp and calculate the seconds. But I am really wondering if Python has a way to do this in a more aesthetic way...

The function do_something() is long-running, and must be interrupted after exactly one second.

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
JohnRoach
  • 747
  • 4
  • 11
  • 26
  • Will it take less than one second, always, and you need to pad it? Will it ever take more than one second, and you want to reduce it? – chmullig Mar 01 '11 at 17:06
  • Please clarify your question. Do you want to (a) run `do_something` once for exactly 1 second and then interrupt it, or (b) do you want to run `do_something` repeatedly until 1 second has passed, or (c) do you want to run `do_something` repeatedly until 1 second has passed *and* interrupt the most recent execution when 1 second passes? – phooji Mar 01 '11 at 17:07
  • no the do_something() function just does something... However it must only do what ever it is doing for only one second. It must cut off what it is doing if it is 1 second. – JohnRoach Mar 01 '11 at 17:08
  • @JohnRoach: so option (a), then? – phooji Mar 01 '11 at 17:10
  • @JohnRoach: I've removed the `while` loop from your question because I think it made people think you were after option (b) or (c). – phooji Mar 01 '11 at 17:25
  • Possible duplicate of [Timeout on a function call](https://stackoverflow.com/questions/492519/timeout-on-a-function-call) – Smart Manoj May 08 '19 at 13:06

3 Answers3

2

I gather from comments that there's a while loop in here somewhere. Here's a class that subclasses Thread, based on the source code for _Timer in the threading module. I know you said you decided against threading, but this is just a timer control thread; do_something executes in the main thread. So this should be clean. (Someone correct me if I'm wrong!):

from threading import Thread, Event

class BoolTimer(Thread):
    """A boolean value that toggles after a specified number of seconds:

    bt = BoolTimer(30.0, False)
    bt.start()
    bt.cancel() # prevent the booltimer from toggling if it is still waiting
    """

    def __init__(self, interval, initial_state=True):
        Thread.__init__(self)
        self.interval = interval
        self.state = initial_state
        self.finished = Event()

    def __nonzero__(self):
        return bool(self.state)

    def cancel(self):
        """Stop BoolTimer if it hasn't toggled yet"""
        self.finished.set()

    def run(self):
        self.finished.wait(self.interval)
        if not self.finished.is_set():
            self.state = not self.state
        self.finished.set()

You could use it like this.

import time

def do_something():
    running = BoolTimer(1.0)
    running.start()
    while running:
        print "running"              # Do something more useful here.
        time.sleep(0.05)             # Do it more or less often.
        if not running:              # If you want to interrupt the loop, 
            print "broke!"           # add breakpoints.
            break                    # You could even put this in a
        time.sleep(0.05)             # try, finally block.

do_something()
senderle
  • 145,869
  • 36
  • 209
  • 233
1

The 'sched' module of Python appears suitable:

http://docs.python.org/library/sched.html

Apart from that: Python is not a real-time language nor does it usually run on a real-time OS. So your requirement is kind of questionable.

  • "Python is not a real-time language" I know I know... I hat it when a language is forced fed to me. It really wasn't my choice. I will check sched. It looks promising. – JohnRoach Mar 01 '11 at 17:19
  • So you are saying basically I should simply schedule my function for each step? – JohnRoach Mar 01 '11 at 17:30
0

This bit of code might work for you. The description sounds like what you want:

http://programming-guides.com/python/timeout-a-function

It relies on the python signal module:

http://docs.python.org/library/signal.html

JoshAdel
  • 66,734
  • 27
  • 141
  • 140
  • Actually, the `signals` module is not unix-only, but the `SIGALRM` signal is. However if you _are_ on unix, this would be a perfect solution. Especially if you don't have control over the contents of `do_something` . – noio Jun 03 '11 at 06:49
  • unfortunately, the link to the website is broken by now - has been caught by a domain hostage service :( – Henning Aug 21 '15 at 11:57