If a KeyboardInterrupt is not handled, the interrupter exits with a special exit code. If I wanted to preserve the exit code, I do something like this:
_prev_excepthook = sys.excepthook
def _excepthook(type, value, traceback):
if not isinstance(value, KeyboardInterrupt):
_prev_excepthook(type, value, traceback)
sys.excepthook = _excepthook
But that’s a lot of code and affects global state. If KeyboardInterrupt had an exit code, we could so something like this:
try:
main()
except KeyboardInterrupt as error:
raise SystemExit(error.exit_code)
Exit codes of keyboard interrupts are weird. If I put raise KeyboardInterrupt in a Python script and run it from a terminal, it uses exit code 130 but if I run it as a subprocess, it’s -2:
The OS in the case of Linux (and MAC OS X). I don’t do Windows. For example, this C program returns 2 if allowed to run for 8 seconds, 130 if Ctrl-C is pressed, 143 if killed (with default 15/SIGTERM), 137 if killed with 9/SIGKILL from another terminal.
I see. So it’s that behavior I want to preserve without Python printing the trace back for the unhandled KeyboardInterrupt. So maybe what I really want is something like this:
True on the *nix systems. Windows is a little different. 3.14 source
static int
exit_sigint(void)
{
/* bpo-1054041: We need to exit via the
* SIG_DFL handler for SIGINT if KeyboardInterrupt went unhandled.
* If we don't, a calling process such as a shell may not know
* about the user's ^C. https://www.cons.org/cracauer/sigint.html */
#if defined(HAVE_GETPID) && defined(HAVE_KILL) && !defined(MS_WINDOWS)
if (PyOS_setsig(SIGINT, SIG_DFL) == SIG_ERR) {
perror("signal"); /* Impossible in normal environments. */
} else {
kill(getpid(), SIGINT);
}
/* If setting SIG_DFL failed, or kill failed to terminate us,
* there isn't much else we can do aside from an error code. */
#endif /* HAVE_GETPID && !MS_WINDOWS */
#ifdef MS_WINDOWS
/* cmd.exe detects this, prints ^C, and offers to terminate. */
/* https://msdn.microsoft.com/en-us/library/cc704588.aspx */
return STATUS_CONTROL_C_EXIT;
#else
return SIGINT + 128;
#endif /* !MS_WINDOWS */
}
This pretty cool. Almost everything I do is on Linux, so this would probably be enough for me. I still think there’s room for lower-level support so you can easily get the exact same behavior as letting it go unhandled.