FTR: nobody on this long thread so far has suggested that there are no
valid use cases for `except Exception`.

Thank you for turning to what happens with 'except ValueError' when an
ExceptionGroup[ValueError] is raised, this is important.

I'm not sure it's safe to assume that it is necessarily a programming
error, and that the interpreter can essentially break the program in this
case.
Is this not allowed?

try:
    try:
        obj.func()    # function that raises ExceptionGroups
    except AttributeError:
        logger.info("obj doesn't have a func")
except *(AttributeError, SyntaxError):
    logger.info("func had some problems")



On Fri, Feb 26, 2021 at 5:40 AM Nathaniel Smith <n...@pobox.com> wrote:

> On Thu, Feb 25, 2021 at 2:13 PM Guido van Rossum <gu...@python.org> wrote:
> >
> > So is "fail-fast if you forget to handle an ExceptionGroup" really a
> feature? (Do we call this out in the PEP?)
> >
> > We may believe that "except Exception" is an abuse, but it is too common
> to dismiss out of hand. I think if some app has e.g. a main loop where they
> repeatedly do something that may fail in many ways (e.g. handle a web
> request), catch all errors and then just log the error and continue from
> the top, it's a better experience if it logs "ExceptionGroup: <message>
> [<list of subexceptions>]" than if it crashes.
>
> Yeah, 'except Exception' happens a lot in the wild, and what to do
> about that has been a major sticking point in the ExceptionGroup
> debates all along. I wouldn't say that 'except Exception' is an abuse
> even -- what do you want gunicorn to do if your buggy flask app raises
> some random exception? Crash your entire web server, or log it and
> attempt to keep going? (This is almost your example, but adding in the
> part where gunicorn is reliable and well-respected, and that its whole
> job is to invoke arbitrarily flaky code written by random users.)
> Yury/I/others did discuss the idea of a
> BaseExceptionGroup/ExceptionGroup split a lot, and I think the general
> feeling is that it could potentially work, but feels like a
> complicated and awkward hack, so no-one was super excited about it.
> For a while we also had a compromise design where only
> BaseExceptionGroup was built-in, but we left it non-final specifically
> so asyncio could define an ExceptionsOnlyExceptionGroup.
>
> Another somewhat-related awkward part of the API is how ExceptionGroup
> and plain-old 'except' should interact *in general*. The intuition is
> that if you have 'except ValueError' and you get an
> 'ExceptionGroup(ValueError)', then the user's code has some kind of
> problem and we should probably do.... something? to let them know? One
> idea I had was that we should raise a RuntimeError if this happens,
> sort of similar to PEP 479. But I could never quite figure out how
> this would help (gunicorn crashing with a RuntimeError isn't obviously
> better than gunicorn crashing with an ExceptionGroup).
>
> == NEW IDEA THAT MAYBE SOLVES BOTH PROBLEMS ==
>
> Proposal:
>
> - any time an unwinding ExceptionGroup encounters a traditional
> try/except, then it gets replaced with a RuntimeError whose __cause__
> is set to the original ExceptionGroup and whose first traceback entry
> points to the offending try/except block
>
> - CUTE BIT I ONLY JUST THOUGHT OF: this substitution happens right
> *before* we start evaluating 'except' clauses for this try/except
>
> So for example:
>
> If an ExceptionGroup hits an 'except Exception': The ExceptionGroup is
> replaced by a RuntimeError. RuntimeError is an Exception, so the
> 'except Exception' clause catches it. And presumably logs it or
> something. This way your log contains both a notification that you
> might want to switch to except* (from the RuntimeError), *along with*
> the full original exception details (from the __cause__ attribute). If
> it was an ExceptionGroup(KeyboardInterrupt), then it still gets caught
> and that's not so great, but at least you get the RuntimeError to
> point out that something has gone wrong and tell you where?
>
> If an ExceptionGroup(ValueError) hits an 'except ValueError': it
> doesn't get caught, *but* a RuntimeError keeps propagating out to tell
> you you have a problem. And when that RuntimeError eventually hits the
> top of your program or ends up in your webserver logs or whatever,
> then the RuntimeError's traceback will point you to the 'except
> ValueError' that needs to be fixed.
>
> If you write 'except ExceptionGroup': this clause is a no-op that will
> never execute, because it's impossible to still have an ExceptionGroup
> when we start matching 'except' clauses. (We could additionally emit a
> diagnostic if we want.)
>
> If you write bare 'except:', or 'except BaseException': the clause
> always executes (as before), but they get the RuntimeError instead of
> the ExceptionGroup. If you really *wanted* the ExceptionGroup, you can
> retrieve it from the __cause__ attribute. (The only case I can think
> of where this would be useful is if you're writing code that has to
> straddle both old and new Python versions *and* wants to do something
> clever with ExceptionGroups. I think this would happen if you're
> implementing Trio, or implementing a higher-level backport library for
> catching ExceptionGroups, something like that. So this only applies to
> like half a dozen users total, but they are important users :-).)
>
> -n
>
> --
> Nathaniel J. Smith -- https://vorpus.org
>
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/VKLL7CIWBVIT26TAX5DVXRIWZF4AJJTJ/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to