Handling signals with Python
2023-05-10 (updated 2025-10-25)Notes | 2 min read
#python
When building a Python script that is long running or has to manage some state on termination it is helpful to handle a couple of signals:
SIGINT: The signal sent when pressing Ctrl+CSIGTERMandSIGQUIT: Meant to terminate the process, sent bykilland process managers like systemd or supervisord
Handling them is possible with Pythons signals library:
import signals
class SignalHandler:
stop = False
def __init__(self):
# Ctrl+C
signal.signal(signal.SIGINT, self.exit_gracefully)
# Supervisor/process manager signals
signal.signal(signal.SIGTERM, self.exit_gracefully)
signal.signal(signal.SIGQUIT, self.exit_gracefully)
def exit_gracefully(self, *args):
self.stop = True
Example 1: Simple loop
The simplest example is using the SignalHandler as the condition on the loop
and have code to stop gracefully below the loop.
print("Starting program")
signal_handler = SignalHandler()
while not signal_handler.stop:
do_something()
print("Saving state and stopping gracefully")
Example 2: Loop with sleep
Sometimes a long running task sleeps for long amounts of time, which makes it impossible to react to the loop condition.
In this case the simplest solution is to break up the large sleep into shorter sleep intervals
and check SignalHandler in between sleeping.
import time
TOTAL_SLEEP = 60
print("Starting program")
signal_handler = SignalHandler()
while not signal_handler.stop:
do_something()
# Instead of time.sleep(TOTAL_SLEEP)
for _ in range(0, TOTAL_SLEEP):
time.sleep(1)
if signal_handler.stop:
break
print("Saving state and stopping gracefully")
The break then brings us out into the while loop,
ending the current iteration and forcing a new check on the while loop,
therefore ending it and allowing the program to end.