views:

585

answers:

5

Is there any way to run one last command before a running Python script is stopped by being killed by some other script, keyboard interrupt etc.

Thanks for your help!

+2  A: 
import signal
import sys
import time

def cleanup(*args):
    print 'Exiting'
    sys.exit(0)

signal.signal(signal.SIGINT, cleanup)
signal.signal(signal.SIGTERM, cleanup)
while True:
    time.sleep(60)  # less busy loop
Dave
Note: although exit() is not async-safe in C, the wording of the Python documentation suggests to me that Python takes care of this problem with some special signal-handling code.
Dave
+1, but the busy loop is *evil*.
Bastien Léonard
I've tested this code on Windows XP, and an error is actually raised because time.sleep() was interrupted. It works on GNU/Linux.
Bastien Léonard
+13  A: 
import time

try:
    time.sleep(10)
finally:
    print "clean up"

clean up
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
KeyboardInterrupt

If you need to catch other OS level interrupts, look at the signal module:

http://docs.python.org/library/signal.html

Signal Example

from signal import *
import sys, time

def clean(*args):
    print "clean me"
    sys.exit(0)

for sig in (SIGABRT, SIGBREAK, SIGILL, SIGINT, SIGSEGV, SIGTERM):
    signal(sig, clean)

time.sleep(10)
Unknown
I have no idea why you chose that particular set, but SIGBREAK doesn't work on non-Windows Pythons, and SIGILL are SIGSEGV are probably not signals that you want to be trapping without a really good reason.
Dave
@Dave its just an example. And its for dan to decide which interrupts he wants to trap.
Unknown
+3  A: 

I think that you could use the atexit module. With it, you can register a function which will be called at program termination. An example from here: http://docs.python.org/library/atexit.html

try:
    _count = int(open("/tmp/counter").read())
except IOError:
    _count = 0

def incrcounter(n):
    global _count
    _count = _count + n

def savecounter():
    open("/tmp/counter", "w").write("%d" % _count)

import atexit
atexit.register(savecounter)

You can also pass positional and keyword parameters to the function you want to call at program termination.

jbradaric
atexit() doesn't fire when the process exits via a signal.
Dave
A: 

Use the atexit module to register a function that will be called at the end.

import atexit
atexit.register(some_function)
Sander Marechal
only works for SIGINT
lispmachine
A: 

I tried with signal library and did it with Netbeans. I mean I ran a program in Netbeans and then terminated it inside Netbeans, but unfortunately it didn't work that way, the function registed with signal wasn't got called. Any suggestion guy?