Register your handler with signal.signal like this:

#!/usr/bin/env python
import signal
import sys

def signal_handler(sig, frame):
    print('You pressed Ctrl+C!')
    sys.exit(0)

signal.signal(signal.SIGINT, signal_handler)
print('Press Ctrl+C')
signal.pause()

Code adapted from here.

More documentation on signal can be found here.  

Answer from Matt J on Stack Overflow
🌐
Python
docs.python.org › 3 › library › signal.html
signal — Set handlers for asynchronous events
Note that installing a signal handler with signal() will reset the restart behaviour to interruptible by implicitly calling siginterrupt() with a true flag value for the given signal. ... Set the handler for signal signalnum to the function handler. handler can be a callable Python object taking two arguments (see below), or one of the special values signal.SIG_IGN or signal.SIG_DFL.
🌐
MicroPython
docs.micropython.org › en › latest › reference › isr_rules.html
Writing interrupt handlers — MicroPython latest documentation
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR’s) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin.
🌐
David Hamann
davidhamann.de › posts › handling and confirming (interrupt) signals in python
Handling and confirming (interrupt) signals in Python | David Hamann
September 29, 2022 - Once set, we overwrite the default behavior and won’t get any KeyboardInterrupts anymore (although you could easily recreate the default behavior by setting the previous handler again, which is returned by signal()). Running the program and then sending an interrupt (<Control-c>) will now look something like this: $ python3 demo.py .....^CHandling signal 2 (SIGINT).
🌐
Readthedocs
pycopy.readthedocs.io › en › latest › reference › isr_rules.html
Writing interrupt handlers — Pycopy 3.6.1 documentation
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR’s) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin.
🌐
MicroPython
docs.micropython.org › en › v1.9.2 › pyboard › reference › isr_rules.html
Writing interrupt handlers — MicroPython 1.9.2 documentation
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR’s) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin.
🌐
MicroPython
docs.micropython.org › en › v1.9.3 › wipy › reference › isr_rules.html
Writing interrupt handlers — MicroPython 1.9.3 documentation
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR’s) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin.
🌐
MicroPython
docs.micropython.org › en › v1.8.5 › wipy › reference › isr_rules.html
Writing interrupt handlers — MicroPython 1.8.5 documentation
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR’s) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin.
Find elsewhere
🌐
MicroPython
docs.micropython.org › en › v1.6 › wipy › reference › isr_rules.html
Writing interrupt handlers — MicroPython 1.6 documentation
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR’s) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin.
🌐
MicroPython
docs.micropython.org › en › v1.8.6 › esp8266 › reference › isr_rules.html
Writing interrupt handlers — MicroPython 1.8.6 documentation
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR’s) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin.
🌐
MicroPython
docs.micropython.org › en › v1.9 › wipy › reference › isr_rules.html
Writing interrupt handlers — MicroPython 1.9 documentation
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR’s) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin.
🌐
MicroPython
docs.micropython.org › en › v1.15 › reference › isr_rules.html
Writing interrupt handlers — MicroPython 1.15 documentation
On suitable hardware MicroPython offers the ability to write interrupt handlers in Python. Interrupt handlers - also known as interrupt service routines (ISR’s) - are defined as callback functions. These are executed in response to an event such as a timer trigger or a voltage change on a pin.
🌐
JBI Training
jbinternational.co.uk › article › view › 3649
How to Send Ctrl-C to Interrupt and Stop a Python Script
November 3, 2023 - Registering the SIGINT signal handler allows the server to exit cleanly. ... import signal def recursive_func(): try: recursive_func() except KeyboardInterrupt: print("Stopping recursion!") The KeyboardInterrupt exception ends the recursion when Ctrl+C is sent by the user. Proper handling of keyboard interrupts allows the creation of scripts that are responsive and resilient. Ctrl-C sends a SIGINT signal that raises a KeyboardInterrupt in Python...
🌐
GeeksforGeeks
geeksforgeeks.org › python › how-to-catch-a-keyboardinterrupt-in-python
How To Catch A Keyboardinterrupt in Python - GeeksforGeeks
July 23, 2025 - Press Ctrl+C to interrupt. Processing step 1 Processing step 2 Processing step 3 Processing step 4 Processing step 5 Exiting the program. Catching KeyboardInterrupt in Python is essential for handling user interruptions gracefully, especially ...
🌐
Tutorialspoint
tutorialspoint.com › python › python_signal_handling.htm
Python - Signal Handling
Python signal handlers are executed in the main Python thread of the main interpreter, even if the signal is received in another thread. Signals can't be used for inter-thread communication. Following are the list of some common signals and their default actions − · SIGINT − Interrupt from keyboard (Ctrl+C), which raises a KeyboardInterrupt.
🌐
Readthedocs
cysignals.readthedocs.io › en › latest › interrupt.html
Interrupt handling — cysignals 1.11.2a0.dev0 documentation
If an interrupt happens during the execution of C or Cython code, it will be caught by the next sig_check(), the next sig_on() or possibly the next Python statement. With the latter we mean that certain Python statements also check for interrupts, an example of this is the print statement.
Top answer
1 of 3
8

It's generally recommended not to use exception calling for flow-control. Instead, look to python stdlib's threading.Event, even if you only plan on using a single thread (even the most basic Python program uses at least one thread).

This answer https://stackoverflow.com/a/46346184/914778 has a good explanation of how calling one function (function b) could interrupt another (function a).

Here's a few important parts, summarized from that other answer.

Set up your threading libraries:

from threading import Event
global exit
exit = Event()

This is a good replacement for time.sleep(60), as it can be interrupt:

exit.wait(60)

This code will execute, until you change exit to "set":

while not exit.is_set():
    do_a_thing()

This will cause exit.wait(60) to stop waiting, and exit.is_set() will return True:

exit.set()

This will enable execution again, and exit.is_set() will return False:

exit.clear()
2 of 3
5

I would do the following:

  • define a custom exception
  • call the callback function within an appropriate try/catch block
  • if the callback function decides to break the execution, it will raise exception and the caller will catch it and handle it as needed.

Here's some pseudo-code:

class InterruptExecution (Exception):
    pass

def function_a():
    while some_condition_is_true():
        do_something()
        if callback_time():
            try:
                function_b()
            except InterruptExecution:
                break
        do_something_else()
    do_final_stuff()


def function_b():
    do_this_and_that()
    if interruption_needed():
        raise (InterruptExecution('Stop the damn thing'))
🌐
Pyodide
pyodide.org › en › stable › usage › keyboard-interrupts.html
Interrupting execution — Version 0.29.3
To use the interrupt system, you should create a SharedArrayBuffer on either the main thread or the worker thread and share it with the other thread. You should use pyodide.setInterruptBuffer() to set the interrupt buffer on the Pyodide thread. When you want to indicate an interrupt, write ...