Skip to main content

We will learn How to capture and handle operating system signals like SIGINT and SIGBREAK on Linux and Windows OS's (Windows 10,11) to control the flow of your python script during execution.

 

Contents

 

Python OS Signals Video Tutorial

 

 

Introduction

We will use the signal module from Python 3 to capture and handle the OS signals.

The tutorial will teach the user to write your own custom signal handler to catch OS signals like

  • SIGINT (CTRL +C )

  • SIGBREAK (CTRL+ BREAK)

and How to register the signal with your custom signal handler and override the default signal behavior.

We will then use the SIGINT ,SIGBREAK  to exit from an infinite loop in Python while closing our open resources like file objects, database connections, serial connections etc in an orderly manner on Linux and Windows systems.

For Eg

In the below example ,we have an infinite loop constantly doing something in the following manner,

Open SerialPort Connection
Open Database Connection

While 1:
        Read from SerialPort
        Write that Data to a Database

Now we want to stop our top pseudo script from what it was doing and exit gracefully while closing all the opened resources like Serial port object or File object.

This where we can use the OS signal to interrupt the execution of our infinite loop.

 

Warning

Some IDE's like Thonny, IDLE etc may interfere with the capture of signals like SIGINT(CTRL+C) or SIGBREAK.

If you are having issues with the signal not triggering your handler function try running the code directly on the command line outside the IDE as shown below (Windows).

D:\> python your_signal_handling_code.py

or on Linux 

$python3 your_signal_handling_code.py

 

Source codes

Website code may be partial or pseudo code just enough to highlight relevant techniques or methods.

Please use the full source codes from our GitHub Repo to avoid errors

 

What are OS Signals

An Operating System Signal is a way in which a program or process (here our python script) can receive information from the Operating System that certain events like a Keyboard Press (CTRL + C ) or a Fault have happened.

Signals are assigned a Integer Value by the OS.

 

operating system signal SIGINT (CTRL +C ) handling tutorial in python 3

 

When we press CTRL + C on our Keyboard the Operating System (Both Windows and Linux) will generate a SIGINT signal that is send to the currently active  program . 

The receiving Program can either execute the default function specified by the SIGINT signal or It can use a signal handler to trap the SIGINT signal and execute  a custom user specified function.

Not all signals are available on all systems. Signals differ between operating systems(Linux/Windows)

 

Checking for available signals in your OS.

Since not all signals are available in every OS, It is good to know which ones are available on your system.

Here we will be using Python 3 (Python 3.9.x) and to access the OS signals we have to import the signal module

import signal    # Import signal module

# available signals on our System
valid_signals = signal.valid_signals()  # requires python 3.9.0
                                        # returns a SET
                                          
print('Number of Available Signals ->', len(valid_signals) , '\n')

for i in valid_signals:
   print(i)

The above partial code will print available signals on a particular OS. Download the full codes from Github

Here  

valid_signals = signal.valid_signals()


returns a set of available OS specific signals which are then printed out.

 

Operating System Signals available on Windows 

On running the signal.valid_signals() function from the Python signal module on Windows 10 (below).

We can see that there are 7 Signals as shown below.

 

python OS Signal handling tutorial on Windows System showing available signals like SIGINT,SIGBREAK

 

On running the signal.valid_signals() function from the Python signal module on Ubuntu Linux System (below).

We can see that there are 62 Signals as shown below.

 

displaying available signals on Linux using python signal.valid_signal() function

 

As you can see from the above images, there are significant differences in the number and types of Signals available in Linux and Windows systems.

 

Programming OS Signals on Python 3 using Signal Module

To use the Signal received by our script we have to do 2 things

  1. Write a Signal Handler which will do the custom processing ,when Signal is received

  2. Register the Signal with the Signal Handler function       
     

#pseudo python code for demo

import signal

def your_custom_signal_handler(signal_number,frame):
          code to do something
          code to do something
          code to do something
          
signal.signal(signal.SIGNALNAME,your_custom_signal_handler)

In the above pseudo code,

we first import the Python signal module to access the various functions.

We then create a custom signal handler function that would run when the operating system notifies our Python Script that a signal has been generated. You can name the signal handler function anything you want.

def your_custom_signal_handler(signal_number,frame):
          code to do something

then we  register the particular signal with our custom signal handling function.

signal.signal(signal.SIGNALNAME,your_custom_signal_handler)

here signal.SIGNALNAME is a place holder and should be replaced by the signal you want to catch. 

Eg signal.SIGINT for catching CTRL+C keyboard interrupt.

Eg signal.SIGBREAK for catching CTRL+BREAK keyboard interrupt.

 

how to configure a signal handler for SIGINT (CTRL+C) or SIGBREAK signal using python signal module in windows and linux

 

Here we will be using the SIGINT signal to control the execution of our Python 3 script.

SIGINT Signal is common to both Windows and Linux systems and helps us to run our code on both Windows and Linux Systems.

Please use the full code from Github

import signal # Import signal module

#signal handler function
def SignalHandler_SIGINT(SignalNumber,Frame):
    print('SignalHandler of signal.SIGINT')
    
#register the signal with Signal handler
signal.signal(signal.SIGINT,SignalHandler_SIGINT)

#infinite signal from which we have to escape
while 1:  
   print("Press Ctrl + C ") 
   time.sleep(1) 

Here

def SignalHandler_SIGINT(SignalNumber,Frame):

is the Signal Handling function ,

When the Signal SIGINT is generated this function is called and the print() statement under is called.

 

The statement

signal.signal(signal.SIGINT,SignalHandler_SIGINT)

registers the signal handler function SignalHandler_SIGINT(SignalNumber,Frame): 

with the signal SIGINT  (signal.SIGINT)

 

Working of Python SIGINT Signal handling Code

If you run the above code ,

  1. The Python script will print "Press CTRL + C" in an infinite loop,
  2. When you hit CTRL +C on the Keyboard , 
  3. A SIGINT signal is generated by the OS (Windows/Linux) and send to the executing script.
  4. The Python script then transfer the control to  def SignalHandler_SIGINT(SignalNumber,Frame): and then executes the print statement under it "SignalHandler of signal.SIGINT"
  5. After which the  control will transfer back to the infinite loop       
     

Please note that the code should be run under the command line as IDE's may interfere with the SIGINT signal.

catching and using SIGINT signal on windows using Python signal module

 

Safely Exiting from an infinite loop in Python using SIGINT signal 

In this example we will learn how to safely exit from an infinite loop in Python 3 using the SIGINT (CTRL+C) signal.

In some application like Serial Port Data Acquisition System Software written in Python we have to query a sensor or Microcontroller like Arduino or Raspberry Pi board continuously in a infinite loop.

In those applications we can use the SIGINT signal (CTRL +C) to interrupt the infinite loop and close the application safely without a resource leak.

You can also use a SIGBREAK (CTRL + BREAK ) signal to do so but the signal is only available in Windows while SIGINT is available on both Linux and Windows.

Please use the full code from GitHub

import signal 
import time 
 
Sentry = True

# Create a Signal Handler for Signals.SIGINT:  CTRL + C 
def SignalHandler_SIGINT(SignalNumber,Frame):
   global Sentry 
   Sentry = False
   
signal.signal(signal.SIGINT,SignalHandler_SIGINT) #regsiter signal with handler

while Sentry: #exit loop when Sentry = False
   print('Long continous event Eg,Read from sensor')
   time.sleep(1)

print('Out of the while loop')
print('Clean up code Here')
  1. Now in the above code we are using a Sentry Variable  to control the flow of the while loop at the bottom
  2. The Sentry Variable is set as True, Sentry = True when the script runs first and the while loop runs continuously.
  3. When the user wants to stop the loop ,he can generate the SIGINT signal by pressing CTRL + C .
  4. The SIGINT signal handler will run and set the Sentry Variable to False .
  5. The control then passes to the While loop where Sentry == False will result in loop terminating and control getting passed to print() statements below.
  6. User can do the cleanup there       
     

Sentry have to defined as Global, inside the signal handler

global Sentry
Sentry = False

 

Getting out of the infinite loop in Python using SIGINT signal on Windows (below)

exiting from a infinite loop in python using SIGINT signal on Windows

Getting out of the infinite loop in Python on Linux using SIGINT signal (below)

getting out of infinite loop in python in linux using SIGINT signals

 

This technique is used to build a Python based serial port data acquisition system here