try:
something()
except:
log_tons_of_debug_info()
raise
and I am very glad that I get my debug info works even if I press Ctrl-C or someone calls sys.exit(). try:
something()
except:
log_tons_of_debug_info()
raise
and I am very glad that I get my debug info works even if I press Ctrl-C or someone calls sys.exit().Correct code would be:
try:
something()
except BaseException as ex:
try:
log_tons_of_debug_info()
finally:
raise ex
But really, you don't want to mess with BaseExceptions at all, so just do `except Exception` instead of a bare `except:`.SystemExit - You _definitely_ want to catch this one for logging. If a library (not top-level app) calls `sys.exit` you at least want to know what's happening, if anything so you can talk to author and get them to use proper exception types.
KeyboardInterrupt - I normally want to catch this one as well. If the program was taking too long and I hit Ctrl-C to stop it, I _do_ want to see all the debug output. And if I don't, for some reason, there is always Ctrl-\ which kills python immediately and unconditionally.
GeneratorExit - this one is tricky and I agree that in a lot of cases, you don't want to print logs on it. But it also very rare - it only appears in async functions (emitted by yield), and never propagated to caller. So as long as you are not doing async, you can simply ignore it, which covers majority of the the code I write.
Your snippet has the opposite problem: if ex is a regular Exception, but then KeyboardInterrupt is raised by `log_tons_of_debug_info()`, then your snippet would mask that by re-raising ex in its place. I think the original snippet is probably better on balance, even ignoring difference in code complexity.
(there is also coredump but most distros disable or hide them, so it's not a problem in practice)
Moreover I think there is a real risk people are going to write "except Exception:" instead, which breaks in the fringe case an exception that derives from BaseException (enforced by interpreter) but not from Exception is thrown.
Even if catch Exception is what users usually mean, changing code from "catch (BaseException):" to "catch Exception:" may break some code if improperly reviewed.
It's also not worth breaking production code over this.
Take that up with the consensus view of the python community, as reflected by python linters in their default configuration, almost all of which warn on bare except.
The debate in the PEP is whether this should be a syntax error. The debate about whether it is good style is over though.
> It's also not worth breaking production code over this.
Agreed.
I don't fully agree on it being a purely a style issue (though the warnings from linters are wholly justified). From what I understand, "except:" is a code smell because you don't actually want to catch BaseException instead of just Exception.
Linters wouldn't have warned about it if it meant "except Exception:". The real issue, IMO, is the fact non-exceptions (Ctrl-C, generator exit, program exit code, etc.) have been crammed into the exception system.
For many users, in many cases, this would be fixing the code rather than breaking it.
Forcing people to write either `except BaseException:` or `except Exception:` means forcing them to think about which one they actually mean. This is a good thing, just like the enforcement of proper separation between bytes and text is a good thing.
There is a good chance it will fail to do that. See elsewhere in this thread.