Thanks a lot for voicing your opinions and concerns! After reading carefully all the arguments, the poll and the different positions we have decided that the best course of action is to withdraw the PEP as there is clear agreement that the breakage doesn’t justify the benefits here.
Personally, I find this feature useless in any production code.
On the other hand, I remember that it was consciously kept (and even repaired after some regression…), by decision of people whose judgment on pythonicity I have complete confidence in.
Just want to say, thanks for listening to the feedback. I was reading through the thread and all set to chime in with a few other arguments why the cost is too high, but then got to your comment here and breathed a sigh of relief. It seems that the proposal is well-intentioned but underestimated the level of disruption, and it’s nice to see that that conclusion can be reached after just a few hours of civil (if occasionally testy) discussion.
One of the goals of the process is to see what is the consensus and PEP proposals are just that: proposals. Having a (civil) discussion is always great and informative. There are always different points of view and weights. We work in this proposals to try to make things better so there is no point to continue the process if there is already community consensus
Yes, it does get thrown around a lot, because it’s supposed to mean something: it means that “if I’m leaving a bare except it’s because I know it’s going to catch everything”.
Having to ask permission to do that, in the form of “except BaseException”, is exactly the opposite of what that phrase means.
I don’t feel like having to write quasi-Java, many of us who prefer to write Python instead of Java, or Typescript, or … any of many über-typed languages, do so exactly because of Python’s loose and dynamic nature.
Adding forced type annotations everywhere on everything will basically turn Python into yet another Java.
Bare except without a bare raise does not have to be a sign of an error, I’ve written many “catch-error-and-continue-running” type code with it, and it’s always a calculated situation.
This should be a linter warning, not a syntax error, nor a syntax warning.
… Really? Your “catch-error-and-continue” code intentionally prevents CTRL+C from aborting the program? That would just be bad code design in most situations.
And if you were not aware that a bare except prevents CTRL+C[1] from working, you are exactly the person this PEP is designed to help.
Some have proposed a (syntax) warning in this thread. Why would the warning be raised at parse time, not at runtime (eg when the except block is exited with no exception set, ie no exception raised)?
I’ve been aware of bare except: being able to catch KeyboardInterrupt, SystemExit and GeneratorExit for many years; usually the construct I follow is a pattern like:
try:
risky_code()
else:
everything_went_well()
except (KeyboardInterrupt, SystemExit, GeneratorExit):
raise
except KnownError:
log.info("Caught the error")
except WonkyDatabaseError:
log.info("The database is wonky")
except:
log.exception("Unknown error I just caught; log it!")
finally:
shut_it_down_forever()
which doesn’t mean I sprinkle except: everywhere in my code, like everything, it’s a tool to be used where it makes sense to use it.
All of this is not unknown, it’s not some obscure detail that’ll bite you if you’re not careful; it’s fully documented and has been discussed for decades. It’s not even like the str() vs unicode() problem that caused the python2 / python3 rift.
I’m all for improvement and change where it makes sense, but this feels a lot like change for the sake of change. The benefits are not concrete, nor enough, to outweigh the costs in code churn, breakage, loss of confidence, cognitive load, and practicality.
This still catches several BaseExceptions in your except block without reraising them.
If that’s actually your intent, had this proposal been accepted, the only change required would have been changing:
except:
to:
except BaseException:
I don’t see how that’s increasing cognitive load, all it’s doing is explicitly spelling out what is to be caught, preventing the situation where someone doesn’t know that that’s the behavior of except:
your example here is something I’d flag in code review even with spelling it out. It supresses control flow exceptions still.
And now your code breaks if python introduces a new non-ExceptionBaseException subclass (idk, maybe ThreadExit, although that ofcourse would not work for various unrelated reasons), and suddenly you have the exact same problem again.
It would be better to just write except Exception, or, if you truly mean it, opt in explicitly by writing except BaseException:. The goal is not to prevent you from doing this, the goal is to prevent you from doing this by accident.
Maybe not you specifically, but beginners? Yes, we are all consenting adults, but beginners to python are not necessarily experienced in these subtle details and will get frustrated and confused if CTRL+C suddenly stops working.[1] Or an careless library author from a library[2] you didn’t quite fully validate before using.
Think about it like this: How much time does it take up for people to learn about this footgun and internalize that it’s an issue over the next 50 years? How many manhours is it going to take to watch out for this footgun during code review (no, not everyone is running a linter with good enough settings). How does that total in manhours compare to the work of running a simple grep accross ~10 million affected lines of code (not counting time it takes to make a release since I would imagine that almost all projects are going to make a release within the next ten years anyway)
Python should strive to improve itself, which means fixing past mistakes when they are recognized. Yes, it would have been better to do this change during 2to3, but now is better than later.
Heck, many of them just aren’t adults. Python is one of the language thought in schools. While this sentence is a nice sentiment, it just isn’t true. ↩︎
A “noone will ever use this” type project for example ↩︎
A proposal to change that might have more success than this proposal did, though. Unlike bare except, I can’t recall encountering a situation where suppressing an exception via the finally clause instead of the except clause was the right thing to do.
It might have had something to do with supporting introspection on sys.exception (akin to the finally e: idea) as an alternative to using the regular exception catching clauses.
Or it might have just been a matter of “continue” originally being disallowed in the compiler because it didn’t work at the runtime implementation level (unlike “return” and “break”, which I believe have worked there since before Python 2.0), so addressing that was approached as a pure bug fix rather than revisiting the underlying language design question of whether or not it should work.
For me, the problem with adding BaseException is that it may mask dodgy code (edited). I have intentionally not added in in IDLE when I did not know what I should add. There were about 20 bare exceptions in about 2012 and I have fixed a few when I thought I knew what should be added. I have left most alone until I edit and am willing to carefully examine the try clause.
I agree, and I would support changing that. Suppressing an exception should be something you are doing very deliberately and explicitly.
break, continue and return are not allowed in except*. The reason given for this in PEP 654 is that they would impact whether or not other except* clauses execute.
Would it be a viable alternative to make it so bare except: means what people usually think it means? That is, change python to make except: equivalent to except Exception: and to restore the older behaviour, people will have to explicitly change their bare excepts to except BaseException: