A gotcha with Python and Unix signals
Python likes to handle things through exceptions. As part of this, on
Unix it does two important signal changes; it ignores SIGPIPE
and
catches SIGINT
. Each of these can make a Python program report
apparent errors where a normal Unix command-line program would just
silently exit.
This matters if you want to write a Python program that will play well
in an ordinary command-line environment, alongside things like cat
,
sed
, and awk
.
First, people expect that they can ^C a Unix command-line program and
have it just quietly stop. Python's default behavior turns this into a
KeyboardInterrupt
exception, which your program is probably not
catching; the user will get a multi-line traceback.
Second and more important, Python ignoring SIGPIPE
means that
your program will get an OSError
exception if it writes to a pipe
that has closed. Pipes close all the time in Unix command pipelines
when you write things like:
generate | mangle.py | head -10
Since head
exits after it's read and printed ten lines, further
output from mangle.py
is probably going to get an OSError
. If you
didn't handle it (do you guard print
statements with try
s?), the
person running this will see a traceback on standard error. People
tend to get irritated when their clean output is messed up with
'error' messages.
(head
is not the only program that will do this, and it doesn't
necessarily happen all the time. Consider what happens when you feed
the output to a pager and quit after seeing the first screen.)
The technique I use for this is:
from signal import signal, \ SIGPIPE, SIGINT, SIG_DFL, \ default_int_handler signal(SIGPIPE, SIG_DFL) s = signal(SIGINT, SIG_DFL) if s != default_int_handler: signal(SIGINT, s)
Checking what SIGINT
is set to is necessary because when your Python
program is being run via nohup
and similar things, SIGINT
will be
set to SIG_IGN
. If we always set SIGINT
to SIG_DFL
, we would
defeat nohup
and irritate the user even more.
(This little thing with SIGINT
is not unique to Python; it's something
you should watch out for in any program where you're setting a SIGINT
handler explicitly. Python itself does it the right way on startup,
leaving a SIG_IGN
setting alone.)
Comments on this page:
|
|