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.
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.
You can treat it like an exception (KeyboardInterrupt), like any other. Make a new file and run it from your shell with the following contents to see what I mean:
import time, sys
x = 1
while True:
try:
print x
time.sleep(.3)
x += 1
except KeyboardInterrupt:
print "Bye"
sys.exit()
Videos
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()
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'))
If a single event is to be handled, then the easiest way is to use the signal framework which is a standard module of Python.
However, if we need a fully-fledged scheduler, then we have to resort to another module: sched. Here is a pointer to the official documentation. Please be aware, though, that in multi-threaded environments sched has limitations with respect to thread-safety.
Another option is the Advanced Python Scheduler, which is not part of the standard distribution.
You can't get real-time without special hardware/software support. You don't need it in most cases (do you need to control giant robots?).
How to delay several function calls by known numbers of seconds depends on your needs e.g., if a time it takes to run a function is negligible compared to the delay between the calls then you could run all functions in a single thread:
#!/usr/bin/env python
from __future__ import print_function
from Tkinter import Tk
root = Tk()
root.withdraw() # don't show the GUI window
root.after(1000, print, 'foo') # print foo in a second
root.after(0, print, 'bar') # print bar in a jiffy
root.after(2000, root.destroy) # exit mainloop in 2 seconds
root.mainloop()
print("done")
It implements yours "I do not want the interrupts to interrupt each other either" because the next callback is not called until the previous one is complete.