Skip to content

Conversation

smurfix
Copy link

@smurfix smurfix commented Sep 8, 2025

Python basically forbids swallowing a BaseException that's not an Exception.

(You do not want a KeyboardInterrupt or a SystemExit to not terminate the program.)

Also, using asyncio, you must always propagate a cancellation.

@aleneum
Copy link
Member

aleneum commented Sep 9, 2025

Hello @smurfix,

Python basically forbids swallowing a BaseException that's not an Exception.

is there a PEP or something where I can look this up?
I just ask because some people specfically asked for catching BaseException (e.g. #619).
Just so that I have a solid argument when somebody asks why this has been changed.

@smurfix
Copy link
Author

smurfix commented Sep 9, 2025

There doesn't seem a PEP-or-whatever documenting this, unfortunately.

https://docs.python.org/3/tutorial/errors.html states

Exceptions which are not subclasses of Exception are not typically handled, because they are used to indicate that the program should terminate. […]

There are a couple of BaseException instances (e.g. GeneratorExit or StopIteration) which don't actually exit the whole program, but they do exit a particular scope and thus catching them and re-raising them somewhere else doesn't make much sense. Same for async cancellation. In that vein I think I'll submit a patch that elaborates on this.

I'm not saying not to call the exception handler, which is what #619 wants us to. My patch specifically does call the handler. It just always propagates the exception instead of eating it, after doing so.

@smurfix
Copy link
Author

smurfix commented Sep 9, 2025

@aleneum
Copy link
Member

aleneum commented Sep 9, 2025

Hi @smurfix,

I'm not saying not to call the exception handler, which is what #619 wants us to. My patch specifically does call the handler. It just always propagates the exception instead of eating it, after doing so.

got it. I absolutely see why 'handling' all exceptions causes unwanted behaviour (KeyboardInterrupt not stopping execution is very unconvenient imo) but I had the impression that's what users want since transitions used to handle Exceptions only in the past.

There are a couple of BaseException instances (e.g. GeneratorExit or StopIteration) which don't actually exit the whole program, but they do exit a particular scope and thus catching them and re-raising them somewhere else doesn't make much sense. Same for async cancellation. In that vein I think I'll submit a patch that elaborates on this.

asyncio.CancelledError is a bit more tricky since it's part of the intended workflow that transitions may cancel long-running callbacks (discussed in #259 as far as I remember). But you are not the only one confused by this (#704, #713). I opted for 'marking' cancellations caused by transitions and only raise cancellations caused by other factors. I happily remove complex exception handling behavior as long as this doesn't render some users' workflow impossible.

I have started https://discuss.python.org/t/forbid-forwarding-or-not-re-raising-a-baseexception/103646 .

looking forward to feedback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants