Introduction
The signal module provides mechanisms to handle asynchronous events like keyboard interrupts and system notifications. Signal handlers define custom responses to signals.
Basic Signal Handling
import signal
import sys
def signal_handler(signum, frame):
print(f"Received signal {signum}")
sys.exit(0)
# Handle SIGINT (Ctrl+C)
signal.signal(signal.SIGINT, signal_handler)
# Handle SIGTERM
signal.signal(signal.SIGTERM, signal_handler)
print("Running... Press Ctrl+C")
signal.pause()
Signal Types
import signal
# Available signals
print(signal.SIGINT) # 2 - Interrupt (Ctrl+C)
print(signal.SIGTERM) # 15 - Termination request
print(signal.SIGKILL) # 9 - Kill (cannot be caught)
print(signal.SIGHUP) # 1 - Hangup
print(signal.SIGALRM) # 14 - Alarm clock
Alarm Signals
import signal
import time
def alarm_handler(signum, frame):
print("Wake up!")
signal.signal(signal.SIGALRM, alarm_handler)
signal.alarm(3) # Set alarm for 3 seconds
print("Waiting...")
signal.pause()
Custom Signal Handlers
import signal
class SignalHandler:
def __init__(self):
self.triggered = False
def __call__(self, signum, frame):
self.triggered = True
print(f"Signal {signum} handled")
handler = SignalHandler()
signal.signal(signal.SIGTERM, handler)
# Raise SIGTERM to test
signal.raise_signal(signal.SIGTERM)
print(handler.triggered)
Ignoring Signals
import signal
# Ignore SIGINT (Ctrl+C won't stop program)
signal.signal(signal.SIGINT, signal.SIG_IGN)
print("Running... Ctrl+C won't stop this")
import time
time.sleep(10)
print("Done")
Process Signals from OS
import signal
import os
import sys
def handle_usr1(signum, frame):
print("USR1 received - performing checkpoint")
# Save state
signal.signal(signal.SIGUSR1, handle_usr1)
# From another terminal: kill -USR1 <pid>
print(f"My PID: {os.getpid()}")
while True:
signal.pause()
Practice Problems
- Handle SIGINT gracefully
- Set alarm with signal.alarm
- Create custom signal handler class
- Ignore specific signals
- Handle SIGUSR1 for user-defined signals