views:

74

answers:

3

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?

+10  A: 

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

Brent Nash
Is there any way to make it where it will be called if you press Ctrl+C or Ctrl+\?
RacecaR
It will be called if you press Ctrl+C. That simply raises a KeyboardInterrupt exception.
Ned Batchelder
Oh, I forgot that. And I assume that nothing you can do will be run if somebody kills the python process right?
RacecaR
@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`.
katrielalex
@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
But you can listen to signals, see the signal module.
THC4k
@Alex Martelli: your comment deserves to be a separate answer
bgbg
+1  A: 

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.

katrielalex
A: 

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:

Brian C. Lane