On Fri, Feb 7, 2020 at 7:47 PM Shai Berger <shai@platonix.com> wrote:
Hi,

In the Django thread, I suggested that an implicit "raise from" should
be the behavior whenever an exception is raised directly in
exception-handling code (that is, within an except: or finally:
clause). Ram claimed there were problems with that, but gave no
details; I would be happy to know what these problems are.

1. Backward compatibility. The meaning of existing plain raises would change, and if irresponsible people depended on it, we'd now break their assumptions. It's annoying and unlikely, but as far as I know python-dev is conservative regarding backward compatibility for esoteric cases. (Remember the non-Ascii Windows version strings? ;)
2. You would then need an explicit way to raise inside an except clause while stating the previous exception wasn't a cause. The syntax `from None` is already taken as "suppress the previous exception", so you'd need to introduce new syntax for that too.
3. The fact that `raise foo` inside `except` means something different than `raise foo` in a function that is called by code inside except, is something that might seem dissonant to many people, myself included.

There might be more problems, I don't know. 

 

The main problem I see with "raise from None" is that it removes the
inner part of the traceback. It expresses the idea that everything that
happened in lower levels is not really interesting -- you should have
all the information for handling or debugging the problem by
considering the flow from here up. I think in most cases where you'd
want to change the type and/or value of an excpetion, this is
unrealistic.

Yeah, I feel the same. I can think of very few good places where `raise foo from None` is beneficial. God, all the times I was desperately troubleshooting a problem, hunting for any glimpse of information of what happened, like looking for drinkable water in a desert... I'd never want to have a traceback excluded, ever.
 

With respect to Ram's current suggestion, I think that for it to really
make a difference, the "raise as" should not be thought of as a
shorthand/variant of "raise ... from", but rather as a variant of bare
raise; that is, it should not create a chained exception, but an effect
of re-raising while changing the exception value (and potentially
type). This, I think, would address Ethan's claim that "this should
really be raise from None", without the cons described earlier; it is a
better expression of the idea "I just want to change the exception being
raised".

To summarize, I am suggesting that

        except ExceptionType:
                raise as OtherException(...)

Have, more-or-less, the semantics of Python 2's:

        except ExceptionType:
                traceback = sys.exc_info()[2]
                raise OtherException, OtherException(...), traceback

This is very interesting. Took me a few reads to understand what you mean, that's an ingenious idea. It's true that the traceback for the new exception would likely be useless and should be thrown away, if it's just one stack level with no information.

However, it is quite a bit of magic, and that's a disadvantage. People don't generally have the expectation that a raise in one location would show a traceback for another location. They might think the lines under the except weren't called, when they were. I wouldn't want it for this reason.