A Python surprise: exiting is an exception

October 20, 2005

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 calls 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 exception called SystemExit.

Naievely (without paying attention to the documentation for the sys module) I had expected sys.exit() to mostly just call the C library exit() function. As the sys module documentation makes clear, this is not what happens: sys.exit() raises 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 broad excepts are dangerous.)

Written on 20 October 2005.
« Accidentally shooting yourself in the foot in Python
MSNbot (still) has problems with binary files »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Thu Oct 20 23:32:25 2005
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.