开发者

break/interrupt a time.sleep() in python

开发者 https://www.devze.com 2023-02-13 03:37 出处:网络
I need to break from time.sleep() using ctrl c. While 1: time.sleep(60) In the above code when the control enters time.sleep function an entire 60 seconds needs to elapsed for python to handled the

I need to break from time.sleep() using ctrl c.

While 1:
    time.sleep(60)

In the above code when the control enters time.sleep function an entire 60 seconds needs to elapsed for python to handled the CTRL C

Is there any elegant way to do it. such that I can interrupt even when the control is in time.sleep function

edit

I was testing it on a legacy implementation which uses python 2.2 on windows 2000 which caused all the trouble . If I had used a higher version of python CTRL C would have interrupte开发者_如何学God the sleep() . I did a quick hack by calling sleep(1) inside a for loop . which temporarily fixed my issue


The correct answer is to use python stdlib's threading.Event

Sure you can tune down your sleep interval so you sleep for very short periods, but what if you actually want to run your loop once every 60s? Then you need to do more work to determine if it's time to run or just keep sleeping. Furthermore, you're still technically blocking but for only a short period of time. Contrast to threading.Event:

from threading import Event

exit = Event()

def main():
    while not exit.is_set():
      do_my_thing()
      exit.wait(60)

    print("All done!")
    # perform any cleanup here

def quit(signo, _frame):
    print("Interrupted by %d, shutting down" % signo)
    exit.set()

if __name__ == '__main__':

    import signal
    for sig in ('TERM', 'HUP', 'INT'):
        signal.signal(getattr(signal, 'SIG'+sig), quit);

    main()

When the signal handler calls exit.set(), the main thread's wait() call will immediately be interrupted.

Now, you could use an Event to signal that there's more work to do, etc. But in this case it does double duty as a convenient indicator that we want to quit (e.g. the while not exit.is_set() part.)

You also have the option to put any cleanup code after your while loop.


Not sure what the sense of this code is - but if necessary use a shorter sleep() interval and put a for loop around it:

for i in range(60):
   sleep(1)

Catching the KeyboardInterrupt exception using try..except is straight-forward


The KeyboardInterrupt exception is raised when a user hits the interrupt key, Ctrl-C. In python this is translated from a SIGINT signal. That means, you can get handle it however you want using the signal module:

import signal

def handler(signum, frame):
    print("do whatever, like call thread.interrupt_main()")

signal.signal(signal.SIGINT, handler)
print("Waiting for SIGINT...")
signal.pause()

That way, you can do whatever you want at the receipt of a keyboard interrupt.


The most elegant solution is certainly threading.Event, though if you only need a quick hack, this code works well :

import time

def main():
    print("It’s time !")

if __name__ == "__main__":
    print("press ctrl-c to stop")
    loop_forever = True
    while loop_forever:
        main()
        try:
            time.sleep(60)
        except KeyboardInterrupt:
            loop_forever = False


I tried your code with python versions 2.5, 2.6, 3 under Linux and all throw "KeyboardInterrupt" exception when hitting CTRL-C.

Maybe some exception handling catches the Interrupt or your problem is like this: Why is KeyboardInterrupt not working in python?


Based on @Andreas Jung answer

        for i in range(360):
            try:
                sleep(1)
            except KeyboardInterrupt:
                sys.exit(0)


Figured I'd throw this in.

import time


def sleep(seconds):
    for i in range(seconds):
        try:
            time.sleep(1)
        except KeyboardInterrupt:
            print("Oh! You have sent a Keyboard Interrupt to me.\nBye, Bye")
            break


sleep(60)
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号