Python Signal Module – What are Signals and How to Create Them?

Python Signal Module

In this article, we’ll take a look at using the Python signal module.

This module is very useful when we want to handle certain signals using Python.

First, let’s look at what a signal means.


What is a Signal?

A Signal is a means through which a program can receive information from the Operating System. When the operating system receives certain events, it can pass that to programs in the form of signals.

For example, when we press the keystrokes Ctrl + C on our keyboard, the Operating System will generate a signal and pass this on to programs. For this particular combination, the signal SIGINT is generated and passed to the programs.

For all common operating systems, there is a standard pattern for assigning these signals, which are generally short for integers.

In Python, these signals are defined in the signal module.

import signal

To look at all the valid signals in your system (depends on the OS), you can use signal.valid_signals()

import signal

valid_signals = signal.valid_signals()

print(valid_signals)

Output

{<Signals.SIGHUP: 1>, <Signals.SIGINT: 2>, <Signals.SIGQUIT: 3>, <Signals.SIGILL: 4>, <Signals.SIGTRAP: 5>, <Signals.SIGABRT: 6>, <Signals.SIGBUS: 7>, <Signals.SIGFPE: 8>, <Signals.SIGKILL: 9>, <Signals.SIGUSR1: 10>, <Signals.SIGSEGV: 11>, <Signals.SIGUSR2: 12>, <Signals.SIGPIPE: 13>, <Signals.SIGALRM: 14>, <Signals.SIGTERM: 15>, 16, <Signals.SIGCHLD: 17>, <Signals.SIGCONT: 18>, <Signals.SIGSTOP: 19>, <Signals.SIGTSTP: 20>, <Signals.SIGTTIN: 21>, <Signals.SIGTTOU: 22>, <Signals.SIGURG: 23>, <Signals.SIGXCPU: 24>, <Signals.SIGXFSZ: 25>, <Signals.SIGVTALRM: 26>, <Signals.SIGPROF: 27>, <Signals.SIGWINCH: 28>, <Signals.SIGIO: 29>, <Signals.SIGPWR: 30>, <Signals.SIGSYS: 31>, <Signals.SIGRTMIN: 34>, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, <Signals.SIGRTMAX: 64>}

Now, for all signals, there are some default actions which the OS will assign to every program.

If we want to have some other behavior instead, we can use signal handlers!


What is a Python Signal Handler?

A Signal Handler is a user defined function, where Python signals can be handled.

If we take the signal SIGINT (Interrupt Signal), the default behavior would be to stop the current running program.

We can, however, assign a signal handler to detect this signal and do our custom processing instead!

Let’s take a look at how we can do this.

import signal  
import time  

# Our signal handler
def signal_handler(signum, frame):  
    print("Signal Number:", signum, " Frame: ", frame)  

def exit_handler(signum, frame):
    print('Exiting....')
    exit(0)

# Register our signal handler with `SIGINT`(CTRL + C)
signal.signal(signal.SIGINT, signal_handler)

# Register the exit handler with `SIGTSTP` (Ctrl + Z)
signal.signal(signal.SIGTSTP, exit_handler)

# While Loop
while 1:  
    print("Press Ctrl + C") 
    time.sleep(3) 

Here, after we run our program, when we press Ctrl + C, the program will go to the signal_handler() function, since we have registered the handler with SIGINT (Ctrl + C).

We also have another handler exit_handler() which exits the program if we press Ctrl + Z, which sends a SIGTSTP signal.

Let’s look at the output

Output

Press Ctrl + C
^CSignal Number: 2  Frame:  <frame at 0x7fe62f033640, file 'python_signals.py', line 22, code <module>>
^ZExiting....

Here, I pressed Ctrl + C to go to the signal_handler() function, and then pressed Ctrl + Z to exit the program. Notice that there is a stack frame object (frame) as well, to track the runtime stack of the main program.


Using Alarm Signals

We can use the SIGALARM signal to send alarm signals to our program. Let’s write a simple signal handler that handles this Python signal.

import signal  
import time  

def alarm_handler(signum, frame):  
    print('Alarm at:', time.ctime())  

# Register the alarm signal with our handler
signal.signal(signal.SIGALRM, alarm_handler)

signal.alarm(3)  # Set the alarm after 3 seconds  

print('Current time:', time.ctime())  

time.sleep(6)  # Make a sufficient delay for the alarm to happen 

In the last line, we sleep for sufficient time (6 seconds) to allow the alarm signal to pass to our program. Otherwise, since the program would have terminated, the signal won’t be received!

Output

Current time: Thu Jul 23 00:41:40 2020
Alarm at: Thu Jul 23 00:41:43 2020

Conclusion

In this article, we learned about how we can set up signal handlers to handle various signals, using the signal module. Visit the link here to learn more about Python modules

References

  • Python signal module Documentation
  • JournalDev article on Python Signals