If we have the following code:
try:
long_running_thing()
finally:
# Some cleanup
And if we're just considering the finally
block running because the user pressed CTRL+C and so KeyboardInterrupt was raised in long_running_thing
... if they press CTRL+C again while in the finally block, could that be interrupted and another KeyboardInterrupt raised?
(And then again... during handing of that KeyboardInterrupt can there be another KeyboardInterrupt raised...)
My aim here is to have robust handling of CTRL+C/KeyboardInterrupt, including multiple CTRL+Cs/KeyboardInterrupts in quick succession
From a bit of testing, the answer is yes, by default another CTRL+C will raise another KeyboardInterrupt
import time
try:
print("Sleeping... press CTRL+C to raise KeyboardInterrupt")
time.sleep(20)
except KeyboardInterrupt:
print("First handler... press CTRL+C again to raise another KeyboardInterrupt")
try:
time.sleep(20)
except KeyboardInterrupt:
print('Second handler')
If you run this and press CTRL+C twice, you'll see Second handler
and showing that KeyboardInterrupt was raised during the first KeyboardInterrupt.
And on
My aim here is to have robust handling of CTRL+C/KeyboardInterrupt
I suspect that if you want really robust handling of CTRL+C, including multiple CTRL+Cs in succession, then Python's default handler of this isn't enough. Instead, I suspect you would have to use Python's signal module to register your own handling of SIGINT, which is the signal that CTRL+C sends to the process, where Python's default handler results in a KeyboardInterrupt raised. You can always store the default handler that raises KeyboardInterrupt before a critical bit of code, and restore it afterwards as well.
Whether this is really needed for a lot of cases: I suspect not - there would be usually more important things to be doing than sorting out this edge case(?)