Monday, August 20, 2012

Initiate debugger using signals

So, I was watching a lightning talk at PyCon AU yesterday, and I think the speaker's first name was Matt. Apologies for not giving a better reference. It all went by pretty quick, but I think I heard something like "Why not use a signal to start the debugger in Python"?

And so I did. I can't work out if this is too trivial to upload to the cheese shop, but if you create a file called "signal_handler.py", and import it from anywhere in your code, you will magically link up the SIGINT (what gets sent by control-C) to the Python debugger. For extra win, it will try to initiate "ipdb" if you have it. I haven't actually tested it on pdb, but it's hard to see how it could fail to work. Besides, you should be using ipdb (pip install ipdb).

import signal

try:
    import ipdb as pdb
except:
    import pdb

def handle_signal(signal_number, frame_stack):
    pdb.set_trace()

signal.signal(signal.SIGINT, handle_signal)

Voila! Now, next time you are watching your app run and you need to start the debugger when you least expected it, you can just do it! 

A small note of caution -- it's probably wrong to override the SIGINT expected behaviour in this way. You could also wire it up to, say, SIGUSR1, but then you would have to explicitly sent the signal with "kill -10". It would work perfectly fine, but is a bit less convenient that just slamming ctrl-c wherever processing happens to be. I'm not sure what else might want/need to sent the occasional SIGINT and rely on normal behaviour, so use this at your own risk!

When you push ctrl-d to end the debugger, you will exit the program.

2 comments:

Catherine said...

Big thanks for this one. I've got some scripts that occasionally seem to get held up forever, and being able to decide retroactively to break in and debug is fantastic!

Tennessee Leeuwenburg said...

Hey, glad it was of use to someone :)