Theresa O’Connor

SIGINFO handling in Python for fun and profit

On Mac OS X and FreeBSD, you can type C-t while a command-line program is running to get a status report from it. This works because both Mac OS X and FreeBSD implement the non-POSIX signal SIGINFO. (Programs receive SIGINFO when there’s been a status request from the keyboard.)

Lots of programs—rsync, for instance— print out something useful about how far along they are when they receive SIGINFO.

I’ve written my share of long-running Python scripts that I fire off from the command line. It’s nice to be able to use SIGINFO to ask such scripts for a status report, and fortunately for us, Python’s signal module makes writing signal handlers easy.

import signal
...
if __name__ == '__main__':
    ...
    signal.signal(signal.SIGINFO, siginfo_handler)
    ...

Assuming you want to run this script under Linux or some other system lacking SIGINFO, we should gracefully degrade by not bombing here.

if hasattr(signal, 'SIGINFO'):
    signal.signal(signal.SIGINFO, siginfo_handler)

Now all that’s left is to implement siginfo_handler.

def siginfo_handler(signum, frame):
    # do something with `frame' here
    pass

The first argument, signum, is simply whatever the value of signal.SIGINFO is, whereas frame is a frame object representing the currently executing Python function. We can examine frame to figure out what your program is up to, to come up with an appropriate message to print to stderr.

For more on frame objects, see the "Frame objects" description in the language reference section on the standard type hierarchy. Basically, you can use frame.f_back to walk up the call tree, and frame.f_locals to examine the current values of any local variables in the frame.