Will Python execute finally block after receiving Ctrl+C

10.1k views Asked by At

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?

4

There are 4 answers

0
Neme On

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.

0
Asclepius On

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
0
Carl On

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).

3
Serge Ballesta On

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