If you stop a python script with Ctrl+C, will it execute any finally blocks, or will it literally stop the script where it is?
Will Python execute finally block after receiving Ctrl+C
10.1k views Asked by generic purple turtle AtThere are 4 answers
Yes, assuming a single Ctrl+C, at least under Linux it will. You can test it with the following Python 3 code:
import time
try:
print('In try.')
time.sleep(1000)
finally:
print(' <-- Note the Ctrl+C.')
for i in range(1, 6):
print(f'Finishing up part {i} of 5.')
time.sleep(.1)
Here is the output:
$ ./finally.py
In try.
^C <-- Note the Ctrl+C.
Finishing up part 1 of 5.
Finishing up part 2 of 5.
Finishing up part 3 of 5.
Finishing up part 4 of 5.
Finishing up part 5 of 5.
Traceback (most recent call last):
File "./finally.py", line 7, in <module>
time.sleep(1000)
KeyboardInterrupt
By default, finally
blocks will run following ctrl-c, as per other answers. However, if someone has overridden the default Python behaviour in an attempt to "avoid ugly KeyboardInterrupt tracebacks", then finally
blocks will not run.
The way I've seen this done is with signal.signal(signal.SIGINT, signal.SIG_DFL)
. That will cause the application to exit immediately without any cleanup as soon as an interrupt is detected. As far as I can tell, this signal handler doesn't even bother to raise a KeyboardInterrupt
. The standard behaviour can be restored by removing the above line or by adding signal.signal(signal.SIGINT, signal.default_int_handler)
.
Well, the answer is mostly it depends. Here is what actually happens:
- Python executes code in a
try:... finally:
block - a Ctrl-C is emitted and is translated in a KeyboardInterrupt Exception
- processing is interrupted and controls passes to the finally block
So at first sight, all works as expected. But...
When a user (not you, but others...) wants to interrupt a task he generally hits multiple times Ctrl-C. The first one will branch execution in the finally
block. If another Ctrl-C occurs in the middle of the finally block because it contains slow operations like closing files, a new KeyboardInterrupt will be raised and nothing guarantees that the whole block will be executed, and you could have something like:
Traceback (most recent call last):
File "...", line ..., in ...
...
KeyboardInterrupt
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "...", line ..., in ...
...
File "...", line ..., in ...
...
KeyboardInterrupt
Yes, it will usually raise a KeyboardInterrupt exception, but remember that your application can be unexpectedly terminated at any time, so you shouldn't rely on that.