== 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 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|http://docs.python.org/lib/module-sys.html]]) 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 _except_s are dangerous|BroadTrys]].)