πΆ 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
SIGINT
andSIGTERM
- 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.,2
for 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
, andSIGHUP
for 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 :