Search code examples
pythonsigintkeyboardinterrupt

How to handle multiple interrupt signals in python?


Let's say I have this script with a function to handle my interrupt signal like so:

import signal
import time
import sys

def handle_interrupt(signum, frame):
   print('Gracefully exiting in 5 seconds...')
   time.sleep(5)
   sys.exit()

signal.signal(signal.SIGINT, handle_interrupt)

print('Sleeping for 5 minutes...')
time.sleep(300)

How can I handle a second interrupt signal so that it quits instantly without waiting 5 additional seconds?


Solution

  • The best way to do it would be to define an interrupt handler object to manage the state of whether the interrupt signal has been received or not already.

    import signal
    import time
    import sys
    
    class InterruptHandler:
        def __init__(self):
            self.interrupted = False
    
        def handle_signal(self, signum, frame):
            if self.interrupted:
                print("Quitting now!")
                sys.exit()
            else:
                print("Quitting in 1 minute!")
                self.interrupted = True
                time.sleep(60)
                sys.exit()
                
    
    interrupt_handler = InterruptHandler()
    
    signal.signal(signal.SIGINT, interrupt_handler.handle_signal)
    
    
    print("Sleeping for 5 minutes...")
    time.sleep(300)
    print("Done sleeping.")
    

    Here's another solution using a global variable to store the "interrupted" state. Using global variables is generally considered bad practice, however.

    import signal
    import time
    import sys
    
    def handle_sigint(signum, frame):
        global interrupted
        if interrupted:
            print("Quitting now!")
            sys.exit()
        else:
            print("Quitting in 1 minute!")
            interrupted = True
            time.sleep(60)
            sys.exit()
    
    signal.signal(signal.SIGINT, handle_sigint)
    interrupted = False
    
    print("Sleeping for 5 minutes...")
    time.sleep(300)
    print("Done sleeping.")