[Python-ideas] Proposal: Abolition of bare except clauses
Chris Angelico
rosuav at gmail.com
Sat Apr 11 15:44:23 CEST 2015
On Sat, Apr 11, 2015 at 11:16 PM, Andrew Barnert <abarnert at yahoo.com> wrote:
> 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...
>
>> 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.
>
I don't have a pile of other Python implementations handy, so I'll
defer to someone else (Steven D'Aprano always seems to have a few
dozen lying around, and might even have a handy script for running
something on all of them and comparing the results!).
>>>>> 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)?
>
That would be an *extremely* weird situation, and could probably be
called a bug. But I don't write C extensions, so again, I'll defer to
someone else on this point.
> And you don't think they'd quickly learn that the way to keep being lazy is to write "except Exception: pass"?
>
> (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?")
>
It's always possible to write bad code. If the bad form is much
shorter and more natural/discoverable than the good, then a lot more
people will write bad code than if they're on par with each other. For
instance, in Py2, it's very easy to write code that's Unicode-unaware
simply by using the obvious string literal style everywhere; it runs
just fine as long as everything's ASCII, and then it breaks on
non-ASCII text. In Py3, you're forced up-front to differentiate
between Unicode and byte strings, and the obvious string literal style
gives you a Unicode string, so people take the obvious route and have
proper Unicode handling.
try: input = raw_input
except NameError: pass
name = input("Enter your name: ")
print("REPORT FOR " + name.upper())
rosuav at sikorsky:~$ python2 ucase.py
Enter your name: Begüm Günceler
REPORT FOR BEGüM GüNCELER
rosuav at sikorsky:~$ python3 ucase.py
Enter your name: Begüm Günceler
REPORT FOR BEGÜM GÜNCELER
It's still possible for your code to be too naive, but you have a
*much* better chance that simplistic code is Unicode-aware in Py3 than
in Py2. Same with exception handling. Sure, you could still have
"except ValueError: pass" and then wonder why your code isn't doing
anything (or, worse, you create a completely different and
hard-to-debug error elsewhere, because your function now returns None
instead of something else - seen that happen a few times), but that's
a lot less subtle than "why does my program go weird when I press
Ctrl-C?" or "why does sys.exit(0) not work here?", which you'll get
from a bare except.
>>> 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...
>
That would be a nuisance, yes. But hopefully that can be deflected
back onto the third-party lib/user-written plugin, basically by
saying:
What's new in MyLibrary v5.7.0:
* Support for Python 3.6
* Old-style class exceptions are no longer supported. If your plugin
defines custom exceptions, be sure that they derive from Exception or
similar.
* other changes, yada yada
Every document I've ever seen has taken one of two attitudes toward
old-style classes. Either they should be considered deprecated, and
every class you define should explicitly subclass something; or
they're a really cool micro-optimization with a few fancy
flexibilities that new-style classes don't have, but which come up
only in the most obscure cases. If a library has to say "old-style
class exceptions can't be supported now due to Python 3.6
compatibility requirements", how many people would actually be up in
arms? It's a VERY small removal of backward compat in favour of
forward compat and cleaner code, just like abolishing string
exceptions was.
However, if it turns out there's some distinct advantage to having
exceptions outside of the primary hierarchy, then I'll withdraw the
suggestion, at least until post-2020 when Py2 support ends (and
probably longer).
ChrisA
More information about the Python-ideas
mailing list