How To Catch “Kill” Events with Python

Currently I’m working on a small MRCPv2 client written in Python, which is part of a bigger project at my laboratory. The client is started remotely by a program which controls and monitors several applications in the whole network and is stopped by it again.

In the Linux world catching “kill events” would be a simple task, to shut down another program a process just has to send a SIGTERM signal which can be caught be Python easily using the signal module which comes with every Python installation. However, on Windows things are a little bit harder, because the operating system never produces SIGTERM (and SIGILL) events according to the signal.h documentation from MSDN. That’s why it took me some time to figure out how to catch “kill” events under Windows with Python.

First of all, there are two different ways to close a program in Windows using the .NET API. The first one is to use Process.Kill which is the Microsoft version of SIGKILL and there is Process.CloseMainWindow which works similar to SIGTERM. To catch the latter one with Python you have to install the pywin32 library and define a handler by using win32api.SetControlCtrlHandler.

Here is a small example how to install an “exit handler” under Linux or Windows:

import os, sys
def set_exit_handler(func):
	if os.name == "nt":
		try:
			import win32api
			win32api.SetConsoleCtrlHandler(func, True)
		except ImportError:
			version = “.”.join(map(str, sys.version_info[:2]))
			raise Exception(”pywin32 not installed for Python ” + version)
	else:
		import signal
		signal.signal(signal.SIGTERM, func)

Use it like this:

if __name__ == "__main__":
	def on_exit(sig, func=None):
		print "exit handler triggered"
		import time
		time.sleep(5)
	set_exit_handler(on_exit)
	print "Press  to quit"
	raw_input()
	print "quit!"

Edit: I’ve cleaned up the code, this version should work with Python 2.4 and 2.6, I didn’t tried it with Python 3000 yet.

About these ads

7 Responses to “How To Catch “Kill” Events with Python”


  1. 1 Mike June 9, 2009 at 6:17 pm

    This doesn’t work at all. I’m using python 2.4 and it’s not showing a damn thing.

  2. 2 Daniel June 16, 2009 at 3:43 pm

    yes you’re right, I’ve checked it with Python 2.4.4 and it doesn’t seem to work with this version, if you upgrade to Python 2.6 it should work

  3. 3 Daniel June 17, 2009 at 12:01 pm

    Yesterday I hadn’t much time so I checked the code with Python 2.4 again today and found that I had installed the wrong version of pywin32, that’s why it didn’t worked under 2.4. However my code sample above is a very dirty script, a better, more cleaner solution should be using os.name to find out whether the code is run under Windows or Linux (or something else), it would work like this:

    import os, sys
    if os.name == “nt”:
    try:
    import win32api
    win32api.SetConsoleCtrlHandler(func, True)
    except ImportError:
    version = “.”.join(map(str, sys.version_info[:3]))
    raise Exception(“pywin32 not installed for Python ” + version)
    else:
    import signal
    signal.signal(signal.SIGTERM, func)

  4. 4 Kevin June 30, 2009 at 2:17 pm

    Unfortunately, I’m finding that this approach works if you CTRL-C the python application but not if you kill it via TaskManager (which probably uses the win32:TerminateProcess call).

    http://msdn.microsoft.com/en-us/library/ms686722(VS.85).aspx

    If a process is terminated by TerminateProcess, all threads of the process are terminated immediately with no chance to run additional code. This means that the thread does not execute code in termination handler blocks. In addition, no attached DLLs are notified that the process is detaching. If you need to have one process terminate another process, the following steps provide a better solution:

  5. 5 mahesh shitole December 7, 2011 at 11:42 am

    hi,

    I have one query.

    I have an test.exe and test.py, my test.py communicating with test.exe using socket,

    I need to stop process of test.exe (without explicit killing) using win32event.setevent, but I m not able to do that, just because my exe is continuously pinging to socket port, how to resolve this problem ?

    please help me!!

  6. 6 Simphony October 19, 2012 at 9:13 pm

    Sadly this only works fine if you run a script on a console with python.exe, but not if you run it in the background with pythonw.exe.

    All I need is a way to catch the terminate signal sent by Windows when I shut the computer down, but I can’t find any way to do it. Atexit doesn’t work either.

  7. 7 j hamowitz November 16, 2012 at 12:24 pm

    This isn’t even signal handling. This is catching the VM exiting and doing something about it. Dummy.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s





Follow

Get every new post delivered to your Inbox.

%d bloggers like this: