No-one expects the string literal exception

Every Python programmer knows that:

    # .. code ..
    print "Caught exception"

is semantically equivalent to:

    # .. code ..
except Exception, e:
    print "Caught exception"

Or is it? Bam:

    raise "No-one expects the string literal exception"
except Exception, e:
    print "Oops, didn't catch this exception"

You'll actually need Python >= 2.5 to reproduce that behaviour, but what's actually neat about all this is that the exception will be caught—without warnings—as you originally expected under Python 2.6, dispite string literals being "truly and utterly dead". See if you can work out why.

Comments (6)

Fred Blasdel

Because the raise statement does "raise TypeError, 'exceptions must be classes or instances, not str'"

It should *really* be a SyntaxError instead.

Aug. 25, 2009, 3:32 a.m. #

PEP 352: Raising a string exception now triggers a TypeError.

Aug. 25, 2009, 7:15 a.m. #

I'll give everyone else a while to guess and/or experiment, but here's a hint: repr(e) is quite illuminating.

Aug. 25, 2009, 7:55 a.m. #

Because raise "foo" will raise a TypeError under Python >= 2.6, which will be caught by the except clause. A good example of why a tight try...except block and a narrow exception type is usually a good idea.

Aug. 25, 2009, 8:41 a.m. #

Semantically equivalent? No, a "bare" try..except: clause catches lots of things you don't want to. KeyboardInterrupt! SystemExit!

Aug. 25, 2009, 8:43 a.m. #
Well, exactly.

On a related note: when I need to get a quick traceback while debugging, I insert


This usually fails because there's no exception to re-raise, but the failure has the traceback that I want.

This is not for production code, obviously.

BTW the original statement about every Python programmer assuming the equivalence of "except:" and "except Exception:" is questionable. I'm sure many Python programmers know about BaseException, which appeared in 2.5.

Aug. 25, 2009, 9:19 a.m. #