How can you have a function or something that will be executed before your program quits? I have a script that will be constantly running in the background, and I need it to save some data to a file before it exits. Is there a standard way of doing this?
6 Answers
Check out the atexit
module:
http://docs.python.org/library/atexit.html
For example, if I wanted to print a message when my application was terminating:
import atexit
def exit_handler():
print 'My application is ending!'
atexit.register(exit_handler)
Just be aware that this works great for normal termination of the script, but it won't get called in all cases (e.g. fatal internal errors).

- 19,075
- 7
- 52
- 56
-
10Is there any way to make it where it will be called if you press Ctrl+C or Ctrl+\? – RacecaR Oct 03 '10 at 15:08
-
11It will be called if you press Ctrl+C. That simply raises a KeyboardInterrupt exception. – Ned Batchelder Oct 03 '10 at 15:11
-
1Oh, I forgot that. And I assume that nothing you can do will be run if somebody kills the python process right? – RacecaR Oct 03 '10 at 15:11
-
6@RacecaR: indeed; the point of killing a process is to stop it dead. From the docs: `Note The exit function is not called when the program is killed by a signal, when a Python fatal internal error is detected, or when os._exit() is called`. – Katriel Oct 03 '10 at 15:12
-
30@RacecaR, the only way you can run termination code even if a process badly crashes or is brutally killed is in **another** process, known as a "monitor" or "watchdog", whose only job is to keep an eye on the target process and run the termination code when apropriate. Of course that requires a very different architecture and has its limitations; if you need such functionality it's best for you to open a different Q on the matter. – Alex Martelli Oct 03 '10 at 15:18
-
-
-
1
-
@katrielalex Not calling the exit function under any circumstances when the process is killed by a signal, if indeed true, would be very unfortunate: it should be possible to trap and handle in Python code some signals such as SIGTERM (the default signal sent by the `kill` command), SIGQUIT, and under some circumstances even SIGHUP. See [this link](http://programmergamer.blogspot.nl/2013/05/clarification-on-sigint-sigterm-sigkill.html). – ack Feb 17 '18 at 10:52
-
FWIW uses a LIFO (Last In, First Out) system for calling functions. – Mattwmaster58 Apr 15 '18 at 02:46
-
1
If you want something to always run, even on errors, use try: finally:
like this -
def main():
try:
execute_app()
finally:
handle_cleanup()
if __name__=='__main__':
main()
If you want to also handle exceptions you can insert an except:
before the finally:

- 715
- 10
- 22

- 4,073
- 1
- 24
- 23
If you stop the script by raising a KeyboardInterrupt
(e.g. by pressing Ctrl-C), you can catch that just as a standard exception. You can also catch SystemExit
in the same way.
try:
...
except KeyboardInterrupt:
# clean up
raise
I mention this just so that you know about it; the 'right' way to do this is the atexit
module mentioned above.

- 120,462
- 19
- 136
- 170
This is a version adapted from other answers. It should work (not fully tested) with graceful exits, kills, and PyCharm stop button (the last one I can confirm).
import signal
import atexit
def handle_exit(*args):
try:
... do computation ...
except BaseException as exception:
... handle the exception ...
atexit.register(handle_exit)
signal.signal(signal.SIGTERM, handle_exit)
signal.signal(signal.SIGINT, handle_exit)

- 3,743
- 9
- 49
- 75
If you have class objects, that exists during the whole lifetime of the program, you can also execute commands from the classes with the __del__(self)
method:
class x:
def __init__(self):
while True:
print ("running")
sleep(1)
def __del__(self):
print("destructuring")
a = x()
this works on normal program end as well if the execution is aborted, for sure there will be some exceptions:
running
running
running
running
running
Traceback (most recent call last):
File "x.py", line 14, in <module>
a = x()
File "x.py", line 8, in __init__
sleep(1)
KeyboardInterrupt
destructuring

- 49
- 5
Based on answers here:
import sys
import atexit
import signal
def exit_handler():
print("Cleaning up")
def kill_handler(*args):
sys.exit(0)
atexit.register(exit_handler)
signal.signal(signal.SIGINT, kill_handler)
signal.signal(signal.SIGTERM, kill_handler)
# MAIN PROGRAM
# for example just reading from the input:
input("Press enter: ")

- 634
- 7
- 7