[Python-ideas] Proposal: Abolition of bare except clauses

Andrew Barnert abarnert at yahoo.com
Sat Apr 11 15:16:24 CEST 2015


On Apr 11, 2015, at 05:39, Chris Angelico <rosuav at gmail.com> wrote:
> 
>> On Sat, Apr 11, 2015 at 10:25 PM, Andrew Barnert <abarnert at yahoo.com> wrote:
>> On Apr 11, 2015, at 04:29, Chris Angelico <rosuav at gmail.com> wrote:
>> 
>> A bare "except:" clause catches any exception. As of Python 3.0, this
>> can be spelled more explicitly as "except BaseException:", and AFAIK
>> the only difference between the two is that someone might rebind
>> BaseException.
>> 
>> String exceptions were abolished during the 2.x line, without causing
>> major upheaval.
>> 
>> 
>> I couldn't remember when this happened, so I look at the docs... But 2.7
>> (https://docs.python.org/2.7/reference/executionmodel.html#exceptions) still
>> say "Exceptions can also be identified by strings, in which case the except
>> clause is selected by object identity." Do the docs need to be fixed?
> 
> 1) Yes, sounds like it.

That worries me a bit. If the docs say strings can be raised in 2.7, even if CPython doesn't allow it, I think you pretty much have to survey every implementation and make sure none of them allow it either before you can feel safe saying it's _just_ a doc problem...

> 2) By identity? Not by equality??

Yeah, I vaguely remember the rule in the old days (as in 2.3-2.5-ish) was identity-or-isinstance.

Of course if you can't actually raise strings in 2.6 and 2.7 (from either Python or C), how they'd be identified if they _were_ raised is kind of irrelevant...

> 3) I have absolutely no idea about string exceptions - I do my best to
> avoid them.

Well, yeah, but if they really do still exist in 2.7 or even 2.6, I think that would count as a strike against removing bare except.

> :)
> 
>> Meanwhile, in the C API
>> (https://docs.python.org/2.7/c-api/exceptions.html#string-exceptions), it
>> says "Changed in version 2.6: All exceptions to be raised or caught must be
>> derived from BaseException." I think that one is correct, but until I sit
>> down at a bigger screen where I can browse the source or run an interpreter,
>> I'm not sure.
> 
> Python 2.7.3 (default, Mar 13 2014, 11:03:55)
> [GCC 4.7.2] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>>>> raise 1
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> TypeError: exceptions must be old-style classes or derived from
> BaseException, not int
>>>> class OldException: pass
> ...
>>>> raise OldException
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> __main__.OldException: <__main__.OldException instance at 0x7f0e6c89e1b8>
> 
> So that one probably needs a docs change too, although it's not as
> serious a problem.

Maybe it means you can't raise them through the public C API, but you can still raise them through Python (or private C functions, presumably)?

(But it also says "caught"; does that mean C code can't use the PyErr_GivenExceptionMatches function to catch your OldException? That would be weird... But not entirely relevant here, so let's not worry about it.)

>> Pros:
>> * Remove the attractive nuisance of "hmm, my code's throwing an error
>> that I don't recognize, I'll use try/except" and just catching
>> everything.
>> 
>> 
>> But if you just teach people "spell that as except BaseException:" (or, more
>> likely, "... as except Exception:"), it's still the exact same attractive
>> nuisance. And, because "except:" is almost always a red flag in novice code,
>> but "except Exception:" is occasionally reasonable, you're making it a tiny
>> bit harder to spot the mistake when helping novices, without actually fixing
>> it.
>> 
>> (Of course requiring an "as" clause would solve all of this, but nobody
>> wants that...)
> 
> So you don't teach people to spell it as "except Exception". You teach
> them to look up the actual exception type they want to catch. That
> already happens, but I've seen quite a bit of code from my own
> students where the shorthand of "except:" is so tempting that it gets
> in. If that came straight back with SyntaxError, they'd be forced to
> put _something_ in, and would be more likely to put in a useful
> exception type.

And you don't think they'd quickly learn that the way to keep being lazy is to write "except Exception: pass"?

That seems overly optimistic to me, but then you're the one teaching classes, so I'll defer to you.

(By the way, even "except TheRightException: pass" is going to be just as bad 90% of the time; they'll still be posting to StackOverflow asking "why my function does nothing and just returns?")

>> Cons:
>> * May make it harder to write Py2/Py3-compatible code. In Py2,
>> "except:" will catch old-style-class exceptions.
>> 
>> 
>> If the C API docs are right and exceptions must be derived from
>> BaseException even in 2.6, they can't be old-style class instances in the
>> first place. (And if anyone's trying to write 2.5/3.x code, they still have
>> to deal with string exceptions, not to mention that they can't get the value
>> of any exceptions they handle, so they've got much bigger problems.)
> 
> Yeah, the wide-span compatibility issue is always going to be there.
> But given that the docs aren't quite right here, this is an issue with
> 2.7/3.x code.

I agree that 2.5 can be pretty much ignored. 2.6, maybe not (a huge percentage of the libs on PyPI right now are 2.6+/3.3+), but it sounds like 2.6 and 2.7 are pretty much identical as far as exceptions anyway?

>> Even if that's not right, what problems do old-style classes cause that
>> new-style-but-not-BaseException-derived classes don't?
> 
> I don't know. I've never consciously raised or caught an old-style
> class. If I unwittingly did, there'd be no problem to any of my code
> if it suddenly started inheriting from Exception or StandardError.

I suspect the issue isn't so much consciously raising them, as, say, conditionally using different third-party libs if they exist (or even using user-written plugins), and one of them raises an old-style class instance, and your app used to catch it and now it doesn't, and you don't notice it until one of your users complains...

> 
> ChrisA
> _______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/


More information about the Python-ideas mailing list