πΆ Python Signal Handling β Graceful Shutdown with SIGINT, SIGTERM
π§² Introduction β Why Handle Signals in Python?
Signals are a core part of Unix-based systems. They allow the OS or other processes to notify your program about events such as:
- Ctrl+C (interrupt via
SIGINT) - Termination (
SIGTERM) - Hang-up (
SIGHUP) - Child process events (
SIGCHLD)
With Pythonβs built-in signal module, you can intercept and handle these events to:
- Shutdown cleanly
- Save state before exit
- Restart services automatically
- Handle timeouts or inter-process communication
π― In this guide, youβll learn:
- What signals are and how they work in Python
- How to catch signals like
SIGINTandSIGTERM - How to safely clean up resources using signal handlers
- Best practices and limitations of signal handling
β What Is a Signal?
A signal is a software interrupt sent to a process to notify it of an event (e.g., kill signal, interrupt signal).
In Python, you can register handlers that are executed when a signal is received.
π§ Setting Up a Signal Handler
β Basic Signal Handler Example
import signal
import sys
def handle_sigint(signum, frame):
print("Caught SIGINT (Ctrl+C). Exiting gracefully...")
sys.exit(0)
signal.signal(signal.SIGINT, handle_sigint)
while True:
pass # Keep running
β Pressing Ctrl+C will now trigger the handler and exit cleanly.
π¦ Supported Signals (Common)
| Signal | Meaning |
|---|---|
SIGINT | Interrupt from keyboard (Ctrl+C) |
SIGTERM | Terminate program (graceful shutdown) |
SIGHUP | Hang-up (e.g., terminal closed) |
SIGCHLD | Child process status changed |
SIGALRM | Alarm signal |
SIGUSR1/2 | Custom user-defined signals |
π§ͺ Example β Handle SIGTERM
def handle_sigterm(signum, frame):
print("Caught SIGTERM. Cleaning up...")
sys.exit(0)
signal.signal(signal.SIGTERM, handle_sigterm)
β Useful in Docker containers, daemonized apps, or system services.
π§ Signal Parameters
The signal handler always accepts two arguments:
def handler(signum, frame):
print(f"Signal received: {signum}")
signum: signal number (e.g.,2for SIGINT)frame: current stack frame (useful for debugging)
π οΈ Using signal.SIGALRM for Timeouts
import time
def timeout_handler(signum, frame):
raise TimeoutError("Operation timed out!")
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(3) # Set a 3-second timer
try:
time.sleep(5) # This will be interrupted
except TimeoutError as e:
print(e)
β Raises a TimeoutError after 3 seconds.
π΅ Limitations of Signal Handling in Python
| Limitation | Details |
|---|---|
| Works only in main thread | Handlers won’t run in background threads |
Can’t catch SIGKILL, SIGSTOP | These signals are uncatchable |
| Handlers must be fast | Avoid blocking or long-running logic |
π§° Real-World Use Case β Graceful Shutdown
import time
running = True
def handle_exit(signum, frame):
global running
print("Shutdown signal received.")
running = False
signal.signal(signal.SIGINT, handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
print("Running... Press Ctrl+C to stop.")
while running:
time.sleep(1)
print("Clean exit complete.")
π‘ Ideal for cleanup scripts, cron jobs, long-running services.
π Best Practices
| β Do This | β Avoid This |
|---|---|
| Register signals early in the program | Delaying signal setup after startup |
Handle SIGINT and SIGTERM together | Ignoring SIGTERM in production apps |
| Use flags (not direct exits) for long loops | Exiting mid-process in multithreaded apps |
| Keep handlers lightweight | Running heavy logic or blocking operations |
π Summary β Recap & Next Steps
Python signal handling allows you to gracefully manage external interrupts and control how your application shuts down or responds to external events.
π Key Takeaways:
- β
Use
signal.signal()to register signal handlers - β
Handle
SIGINT,SIGTERM, andSIGHUPfor clean shutdowns - β Signals only affect the main thread
- β
Use
signal.alarm()to implement timeouts
βοΈ Real-World Relevance:
Used in system daemons, CLI tools, Docker containers, and supervised services like Gunicorn, Celery, or custom schedulers.
β FAQ β Python Signal Handling
β Can Python catch Ctrl+C?
β
Yes. Use signal.SIGINT to handle keyboard interrupts.
β Can I handle signals in threads?
β No. Signal handlers only work in the main thread.
β How do I stop a long-running loop using signals?
β Set a global flag in the handler and check it inside the loop.
β What signals canβt be handled?
SIGKILL(9)SIGSTOP(19)
These cannot be caught or ignored.
β Whatβs the difference between SIGINT and SIGTERM?
SIGINT: Sent by keyboard (Ctrl+C)SIGTERM: Sent by system/process, often to gracefully stop a program
Share Now :
