How to stop an infinite loop safely in Python? How to stop an infinite loop safely in Python? python python

How to stop an infinite loop safely in Python?


What you need to do is catch the interrupt, set a flag saying you were interrupted but then continue working until it's time to check the flag (at the end of each loop). Because python's try-except construct will abandon the current run of the loop, you need to set up a proper signal handler; it'll handle the interrupt but then let python continue where it left off. Here's how:

import signalimport time   # For the demo onlydef signal_handler(signal, frame):    global interrupted    interrupted = Truesignal.signal(signal.SIGINT, signal_handler)interrupted = Falsewhile True:    print("Working hard...")    time.sleep(3)    print("All done!")    if interrupted:        print("Gotta go")        break

Notes:

  1. Use this from the command line. In the IDLE console, it'll trample on IDLE's own interrupt handling.

  2. A better solution would be to "block" KeyboardInterrupt for the duration of the loop, and unblock it when it's time to poll for interrupts. This is a feature of some Unix flavors but not all, hence python does not support it (see the third "General rule")

  3. The OP wants to do this inside a class. But the interrupt function is invoked by the signal handling system, with two arguments: The signal number and a pointer to the stack frame-- no place for a self argument giving access to the class object. Hence the simplest way to set a flag is to use a global variable. You can rig a pointer to the local context by using closures (i.e., define the signal handler dynamically in __init__(), but frankly I wouldn't bother unless a global is out of the question due to multi-threading or whatever.

Caveat: If your process is in the middle of a system call, handling an signal may interrupt the system call. So this may not be safe for all applications. Safer alternatives would be (a) Instead of relying on signals, use a non-blocking read at the end of each loop iteration (and type input instead of hitting ^C); (b) use threads or interprocess communication to isolate the worker from the signal handling; or (c) do the work of implementing real signal blocking, if you are on an OS that has it. All of them are OS-dependent to some extent, so I'll leave it at that.


the below logic will help you do this,

import signalimport sysimport timerun = Truedef signal_handler(signal, frame):    global run    print "exiting"    run = Falsesignal.signal(signal.SIGINT, signal_handler)while run:    print "hi"    time.sleep(1)    # do anything    print "bye"

while running this, try pressing CTRL+C


I hope below code would help you:

#!/bin/pythonimport sysimport timeimport signaldef cb_sigint_handler(signum, stack):    global is_interrupted    print "SIGINT received"    is_interrupted = Trueif __name__ == "__main__":    is_interrupted = False    signal.signal(signal.SIGINT, cb_sigint_handler)    while(1):        # do stuff here         print "processing..."        time.sleep(3)        if is_interrupted:            print "Exiting.."            # do clean up            sys.exit(0)