Tom Ritchford
1 min readNov 23, 2023


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:
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.