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.