You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When raising inside except* block and the caught exception wasn't an ExceptionGroup originally, then raised exception doesn't get wrapped in ExceptionGroup:
try:
try:
raiseTypeError(1) # prints ValueError(3)raiseExceptionGroup('', [TypeError(2)]) # prints ExceptionGroup('', [ValueError(3)])
except* TypeError:
raiseValueError(3)
exceptBaseExceptionase:
print(repr(e))
Your environment
CPython versions tested on: 3.11.3
Operating system and architecture: Windows 11 / Ubuntu 22.04
Raising a new instance of a naked exception does not cause this exception to be wrapped by an exception group. Rather, the exception is raised as is, and if it needs to be combined with other propagated exceptions, it becomes a direct child of the new exception group created for that.
@sunmy2019 thanks for the docs pointer. It is a bit confusing behavior for me, since I can't always be sure what I'm actually raising. But I guess we can close this then?
is that the raised exception group includes both a ValueError (will be caught by the except* ValueError) and a TypeError (is not caught and thus must be propagated.) It is the latter TypeError that means the newly raised KeyError "needs to be combined with other propagated exceptions" (the TypeError), and thus a new ExceptionGroup is created for that.
the original exception group contains only a TypeError, which is caught by except* TypeError. So there are no remaining uncaught exceptions that must propagate along with the newly raised ValueError. So according to the wording in the PEP:
Rather, the exception is raised as is, and if it needs to be combined with other propagated exceptions, it becomes a direct child of the new exception group created for that
it is surprising (to me -- not an expert in the ExceptionGroup feature by any means) that a new ExceptionGroup would be created containing just the newly-raised ValueError.
Any remaining exceptions that were not handled by any except* clause are re-raised at the end, combined into an exception group along with all exceptions that were raised from within except* clauses.
This wording is more ambiguous than the wording in the PEP, and leaves open the possibility that a new exception group should always be created, even if we are raising just a single exception and there were no "remaining exceptions" to propagate.
So it is possible this is intended behavior, but it doesn't seem at all clear. I think we need input from @iritkatriel here.
I agree that the wording of the PEP implies that wrapping in an exception group should not happen unless it is necessary, and it is not necessary when there is only one exception.
I don't remember why I implemented it this way (with unit tests asserting this behaviour, no less). I'm going to assume that it was a simple mistake and make a PR to fix it. Will ask @gvanrossum for a second option.
Activity
mdboom commentedon Apr 17, 2023
Cc: @iritkatriel
sunmy2019 commentedon Apr 17, 2023
This is fully documented behavior. https://peps.python.org/pep-0654/#raising-new-exceptions
andriilahuta commentedon Apr 17, 2023
@sunmy2019 thanks for the docs pointer. It is a bit confusing behavior for me, since I can't always be sure what I'm actually raising. But I guess we can close this then?
carljm commentedon Apr 17, 2023
I don't think that the issue in the OP here clearly matches any example shown in the PEP. The key factor in the PEP example:
is that the raised exception group includes both a
ValueError(will be caught by theexcept* ValueError) and aTypeError(is not caught and thus must be propagated.) It is the latterTypeErrorthat means the newly raisedKeyError"needs to be combined with other propagated exceptions" (theTypeError), and thus a newExceptionGroupis created for that.In the OP example:
the original exception group contains only a
TypeError, which is caught byexcept* TypeError. So there are no remaining uncaught exceptions that must propagate along with the newly raisedValueError. So according to the wording in the PEP:it is surprising (to me -- not an expert in the ExceptionGroup feature by any means) that a new
ExceptionGroupwould be created containing just the newly-raisedValueError.The documentation says about this case:
This wording is more ambiguous than the wording in the PEP, and leaves open the possibility that a new exception group should always be created, even if we are raising just a single exception and there were no "remaining exceptions" to propagate.
So it is possible this is intended behavior, but it doesn't seem at all clear. I think we need input from @iritkatriel here.
pythongh-103590: do not wrap a single exception raised from a try-exc…
iritkatriel commentedon Apr 21, 2023
I agree that the wording of the PEP implies that wrapping in an exception group should not happen unless it is necessary, and it is not necessary when there is only one exception.
I don't remember why I implemented it this way (with unit tests asserting this behaviour, no less). I'm going to assume that it was a simple mistake and make a PR to fix it. Will ask @gvanrossum for a second option.
gh-103590: do not wrap a single exception raised from a try-except* (#…
pythongh-103590: do not wrap a single exception raised from a try-exc…
[3.11] gh-103590: do not wrap a single exception raised from a try-ex…
gh-103590: mention that the change is included in 3.11.4 and clarify …
Merge #793
Update python-exceptiongroup to version 1.1.2 / rev 6 via SR 1096944
Merge #837
Merge #893
Bump exceptiongroup from 1.2.0 to 1.2.1 (#76)
Bump exceptiongroup from 1.2.0 to 1.2.1 (#1045)
Merge #953
Bump exceptiongroup from 1.2.0 to 1.2.1 in /src/python (#106)
Bump the dependencies group across 1 directory with 17 updates (#4254)
Bump exceptiongroup from 1.2.1 to 1.2.2 (#234)
Bump exceptiongroup from 1.2.1 to 1.2.2 (#111)
Merge #999
Bump exceptiongroup from 1.1.2 to 1.2.2 (#8812)
Bump exceptiongroup from 1.1.2 to 1.2.2 (#8861)