I want to catch KeyboardInterrupt
globally, and deal with it nicely. I don't want to encase my entire script in a huge try/except statement. Is there any way to do this?
Asked
Active
Viewed 5.3k times
5 Answers
152
You could change sys.excepthook
if you really don't want to use a try/except
.
import sys
def my_except_hook(exctype, value, traceback):
if exctype == KeyboardInterrupt:
print "Handler code goes here"
else:
sys.__excepthook__(exctype, value, traceback)
sys.excepthook = my_except_hook

andrewrk
- 30,272
- 27
- 92
- 113

multipleinterfaces
- 8,913
- 4
- 30
- 34
-
17Use `sys.__excepthook__` which contains the original value of `sys.excepthook` instead of manually saving it. – wap26 Oct 22 '13 at 09:52
-
1Great point; I didn't realize `sys.__excepthook__` would retain the old value. – multipleinterfaces Oct 22 '13 at 13:17
-
3Saving the old one and calling it has the advantage that several `excepthook`s can be chained. – glglgl Oct 22 '13 at 13:26
-
3Would this also catch the exceptions thrown by a thread spawned by the main thread? – Pankaj Parashar Aug 12 '15 at 09:43
-
@PankajParashar See [this](http://stackoverflow.com/questions/1643327/sys-excepthook-and-threading) thread. – akhan Dec 21 '16 at 00:48
-
Will this prevent from crashing when unhandled exception occurs? – Filip Š Dec 13 '18 at 19:13
-
4As-written, this only suppresses the interruption due to `KeyboardInterrupt`. All other exceptions will still result in the same behavior as though the `sys.excepthook` were not changed. – multipleinterfaces Dec 14 '18 at 18:49
-
1Another wrong accepted answer. See answer by @mouad for the right way to handle `KeyboardInterrupt`s. – Bachsau Jun 09 '19 at 18:49
-
I like @mouad's solution much better... but I absolutely love the fact that you can just go ahead and **do this** in Python. – Teekin Nov 19 '19 at 20:40
25
If this is a script for execution on the command line, you can encapsulate your run-time logic in main()
, call it in an if __name__ == '__main__'
and wrap that.
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print 'Killed by user'
sys.exit(0)

Rob Cowie
- 22,259
- 6
- 62
- 56
-
4This won't handle uncaught exceptions in other threads, besides your main thread. As multipleinterfaces suggested, sys.excepthook is the way to go – Orlin Georgiev Aug 11 '16 at 13:42
-
@OrlinGeorgiev [This](http://stackoverflow.com/questions/1643327/sys-excepthook-and-threading) thread says otherwise. – akhan Dec 21 '16 at 00:47
-
This also won't help you when the exception is raised somewhere up the call stack and you have exception handlers between there & the top level. – Noah Jan 24 '22 at 17:47
21
You can also use signal like this:
import signal, time
def handler(signum, frame):
print 'I just clicked on CTRL-C '
signal.signal(signal.SIGINT, handler)
print "waiting for 10 s"
time.sleep(10)
Output:
waiting for 10 s
^CI just clicked on CTRL-C
N.B: Don't mix the use of signal with threads.

mouad
- 67,571
- 18
- 114
- 106
-
4
-
2There is no problem with using signals in python threads. You just need to be aware of the fact, that you need to set the handler from the main threads and that it is always executed in the main thread. The default `KeyboardInterrupt` exception is also raised from a signal handler. – Bachsau Jun 09 '19 at 18:53
10
Does your script have a function you call to start it?
main()
then just do:
try:
main()
except:
...
If you don't have a main
but just a huge script that runs line-by-line, then you should put it in a main
.

Claudiu
- 224,032
- 165
- 485
- 680
0
There's no other way to do this, apart from encasing your entire script in a main()
function and surrounding that with a try..except
block - which is pretty much the same:
def main():
# Your script goes here
pass
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
# cleanup code here
pass

Tamás
- 47,239
- 12
- 105
- 124
-
2The suggestion is valid, but it's incorrect that there is no other way, as demonstrated by other answers. – Teekin Nov 19 '19 at 20:37