Handle KeyboardInterrupt in Python
Error Reference
KeyboardInterrupt
Ctrl+C raised an exception on purpose. Decide whether to clean up, exit quietly, or keep running.
Graceful shutdown
KeyboardInterrupt isn't a bug — it's how Python delivers Ctrl+C so your program gets a chance to exit cleanly instead of dying mid-write:
import sys
def main():
while True:
process_next_item()
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print('\nInterrupted — shutting down cleanly.')
sys.exit(130) # conventional exit code for SIGINT
Cleanup with finally
Resources should be released whether the program finishes or gets interrupted — finally (and with blocks) run in both cases:
conn = open_connection()
try:
run_forever(conn)
except KeyboardInterrupt:
print('Stopping…')
finally:
conn.close() # runs on normal exit AND on Ctrl+C
Why except Exception doesn't catch it
KeyboardInterrupt inherits from BaseException, not Exception — deliberately, so a broad except Exception in a retry loop can't swallow your Ctrl+C and turn the program unkillable:
BaseException
├── SystemExit
├── KeyboardInterrupt <- outside the Exception branch
└── Exception
├── ValueError
├── TypeError
└── ...
while True:
try:
do_work()
except Exception: # errors are retried…
continue
# …but Ctrl+C still stops the loop
This is also the core reason a bare except: is a bug: it catches BaseException and makes the process ignore Ctrl+C.
Long-running services
For servers and workers, translate the signal into an orderly stop instead of an exception mid-task:
import signal
stop = False
def request_stop(signum, frame):
global stop
stop = True
signal.signal(signal.SIGINT, request_stop)
while not stop:
process_one_batch() # finishes the current batch, then exits
print('Drained cleanly.')
Frequently Asked Questions
Should I catch KeyboardInterrupt at all?
Catch it once, at the top level, to clean up and exit — closing files, committing or rolling back transactions, printing a friendly message. Avoid catching it deep inside loops or libraries, where suppressing it makes the program hard to stop.
Why does my program ignore Ctrl+C?
Usually a bare except: or except BaseException: somewhere is swallowing the KeyboardInterrupt. Blocking C extensions or threads can also delay delivery — in threads, only the main thread receives KeyboardInterrupt.
try:
risky()
except Exception: # not bare 'except:' — Ctrl+C passes through
handle()
What exit code should a Ctrl+C exit use?
Convention on Unix is 130 (128 + SIGINT signal number 2). Shells and process supervisors use it to distinguish "user interrupted" from success (0) or failure (1).