Good article, but as written, the above sentence is not right at all!
The most important rule is this: don't catch exceptions at all unless you can completely handle them.
It's much, much better for a program to crash than it is to continue with things in a bad state.
Here’s an example from a current project of mine! Almost all the error handling is right at the top:
def run() -> int:
try:
app(prog_name='recs', standalone_mode=False)
return 0
except RecsError as e:
print('ERROR:', *e.args, file=sys.stderr)
except click.ClickException as e:
print(f'{e.__class__.__name__}: {e.message}', file=sys.stderr)
except click.Abort:
print('Aborted', file=sys.stderr)
return -1
I know exactly what each of these exceptions means.
RecsError
is my own, and it means an “expected” error that can be explained to the user: for example, elsewhere in the code is a line like raise RecsError(‘No devices or channels selected’)
.
ClickException
and click.Abort
both come from the CLI package I use: the first indicates an error in a command line flag, the second a control-C.
Any other exception causes the program to crash. When I started development this happened a lot but it hasn’t happened in ages.
Great article in general, though, I particularly like the systematic nature of it.