A Python surprise: exiting is an exception
Once upon a time I wrote a program to scan incoming mail messages during the SMTP conversation for signs of spam. Because this was running as part of our mailer, reliability was very important; unhandled errors could cause us to lose mail.
As part of reliability, I decided I wanted to catch any unhandled exception (which would normally abort the program with a backtrace), log the backtrace, save a copy of the message that caused the bug, and so on. So I wrote code that went like this:
def catchall(M, routine): try: routine(M) except: # log backtrace, etc
The mail checking routine told the mailer whether to accept or reject
the message through the program's exit status code, so the routine
sys.exit() when it's done.
Then I actually ran this code, and the first time through it dutifully
spewed a backtrace into the logs about the code raising an unhandled
Naievely (without paying attention to the documentation for the
sys module) I had
sys.exit() to mostly just call the C library
function. As the sys module documentation makes clear, this is not
SystemExit, the whole chain of
exception handling happens (in part so that
finally clauses get
executed), and at the top of the interpreter you finally exit.
Unless, of course, you accidentally catch
SystemExit. Then very odd
things can happen.
(This is another example of why
excepts are dangerous.)